diff --git a/src/main/kotlin/util/files.kt b/src/main/kotlin/util/files.kt index 3743fe684..cf356e91c 100644 --- a/src/main/kotlin/util/files.kt +++ b/src/main/kotlin/util/files.kt @@ -3,7 +3,7 @@ * * https://mcdev.io/ * - * Copyright (C) 2025 minecraft-dev + * Copyright (C) 2026 minecraft-dev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published @@ -33,6 +33,8 @@ import java.nio.file.Path import java.util.jar.Attributes import java.util.jar.JarFile import java.util.jar.Manifest +import kotlin.coroutines.resume +import kotlinx.coroutines.suspendCancellableCoroutine val VirtualFile.localFile: File get() = VfsUtilCore.virtualToIoFile(this) @@ -80,17 +82,20 @@ operator fun Manifest.get(attribute: String): String? = mainAttributes.getValue( operator fun Manifest.get(attribute: Attributes.Name): String? = mainAttributes.getValue(attribute) suspend fun VirtualFile.refreshSync(modalityState: ModalityState): VirtualFile? { - fun refresh() { - RefreshQueue.getInstance().refresh(false, this.isDirectory, null, modalityState, this) + // RefreshSessionImpl asserts a write-safe context in its constructor, which fails when called + // from a modal dialog's dispatched coroutine. We schedule the refresh via invokeLater with + // the correct ModalityState so TransactionGuard sees a write-safe context. + suspendCancellableCoroutine { cont -> + ApplicationManager.getApplication().invokeLater( + { + RefreshQueue.getInstance().refresh(false, this.isDirectory, null, modalityState, this) + cont.resume(Unit) + }, + modalityState, + ) } - if (ApplicationManager.getApplication().isWriteAccessAllowed) { - refresh() - } else { - writeAction { - refresh() - } + return writeAction { + this@refreshSync.parent?.findOrCreateChildData(this@refreshSync, this@refreshSync.name) } - - return this.parent?.findOrCreateChildData(this, this.name) }