Skip to content

Commit e99d90f

Browse files
committed
Merge branch '2026.1' into 2026.2
2 parents 74ee162 + 33f8e8f commit e99d90f

13 files changed

Lines changed: 107 additions & 67 deletions

File tree

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ dependencies {
122122
bundledModule("intellij.platform.langInjection")
123123
bundledPlugin("com.intellij.properties")
124124
bundledPlugin("Git4Idea")
125+
bundledModule("intellij.platform.collaborationTools")
125126
bundledPlugin("com.intellij.modules.json")
126127

127128
// Optional dependencies

changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Minecraft Development for IntelliJ
22

3+
## [1.8.18]
4+
5+
### Fixed
6+
7+
- Write-unsafe context errors during project creation
8+
39
## [1.8.17]
410

511
### Added

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ org.gradle.jvmargs=-Xmx1g
2323

2424
ideaVersionName = 2026.2
2525

26-
coreVersion = 1.8.17
26+
coreVersion = 1.8.18
2727

2828
# Silences a build-time warning because we are bundling our own kotlin library
2929
kotlin.stdlib.default.dependency = false

readme.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ Minecraft Development for IntelliJ
1111
<td align="right"><b>Main Build</b></td>
1212
<td colspan="2"><a href="https://ci.mcdev.io/viewType.html?buildTypeId=MinecraftDev_Build"><img src="https://ci.mcdev.io/app/rest/builds/buildType:(id:MinecraftDev_Build)/statusIcon.svg" alt="Teamcity Build Status" /></a></td>
1313
</tr>
14-
<tr>
15-
<td align="left">2025.2</td>
16-
<td align="left"><a href="https://ci.mcdev.io/viewType.html?buildTypeId=MinecraftDev_Nightly_20252"><img src="https://ci.mcdev.io/app/rest/builds/buildType:(id:MinecraftDev_Nightly_20252)/statusIcon.svg" alt="2025.2 Nightly Status" /></a></td>
17-
</tr>
1814
<tr>
1915
<td align="left">2025.3</td>
2016
<td align="left"><a href="https://ci.mcdev.io/viewType.html?buildTypeId=MinecraftDev_Nightly_20253"><img src="https://ci.mcdev.io/app/rest/builds/buildType:(id:MinecraftDev_Nightly_20253)/statusIcon.svg" alt="2025.3 Nightly Status" /></a></td>

src/main/kotlin/creator/JdkComboBoxWithPreference.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import com.intellij.openapi.util.Condition
4141
import com.intellij.openapi.util.Disposer
4242
import com.intellij.ui.dsl.builder.Cell
4343
import com.intellij.ui.dsl.builder.Row
44+
import com.intellij.util.SlowOperations
4445
import javax.swing.JComponent
4546

4647
internal class JdkPreferenceData(
@@ -176,7 +177,13 @@ fun Row.jdkComboBoxWithPreference(
176177
}
177178

178179
val lastUsedSdk = stateComponent.getValue(selectedJdkProperty)
179-
ProjectWizardUtil.preselectJdkForNewModule(project, lastUsedSdk, comboBox) { true }
180+
// preselectJdkForNewModule -> setSelectedJdk -> combo renderer -> LocalFileSystem.findFileByPath
181+
// triggers a SlowOperations violation since the combo renderer does VFS I/O on the EDT.
182+
// This is entirely platform code we don't own, so allowSlowOperations is the only "solution".
183+
@Suppress("UnstableApiUsage")
184+
SlowOperations.knownIssue("IDEA-364789").use {
185+
ProjectWizardUtil.preselectJdkForNewModule(project, lastUsedSdk, comboBox) { true }
186+
}
180187

181188
val windowChild = context.getUserData(AbstractWizard.KEY)!!.contentPanel
182189
comboBox.loadSuggestions(windowChild, context.disposable)

src/main/kotlin/creator/custom/CreatorTemplateProcessor.kt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ class CreatorTemplateProcessor(
230230
val templateProperties = collectTemplateProperties()
231231
thisLogger().debug("Template properties: $templateProperties")
232232

233-
val generatedFiles = mutableListOf<Pair<TemplateFile, VirtualFile>>()
233+
val generatedFiles = mutableListOf<Pair<TemplateFile, Path>>()
234234
for (file in template.descriptor.files.orEmpty()) {
235235
if (file.condition != null &&
236236
!TemplateEvaluator.condition(templateProperties, file.condition).getOrElse { false }
@@ -270,12 +270,7 @@ class CreatorTemplateProcessor(
270270
destPath.parent.createDirectories()
271271
destPath.writeText(processedContent)
272272

273-
val virtualFile = destPath.refreshAndFindVirtualFile()
274-
if (virtualFile != null) {
275-
generatedFiles.add(file to virtualFile)
276-
} else {
277-
thisLogger().warn("Could not find VirtualFile for file generated at $destPath (descriptor: $file)")
278-
}
273+
generatedFiles.add(file to destPath)
279274
} catch (t: Throwable) {
280275
if (t is ControlFlowException) {
281276
throw t
@@ -291,8 +286,12 @@ class CreatorTemplateProcessor(
291286
// Apparently a module root is required for the reformat to work
292287
setupTempRootModule(project, projectPath)
293288

294-
reformatFiles(project, generatedFiles)
295-
openFilesInEditor(project, generatedFiles)
289+
val genVirtualFiles = generatedFiles
290+
.mapNotNullTo(mutableListOf()) {
291+
it.first to (it.second.refreshAndFindVirtualFile() ?: return@mapNotNullTo null)
292+
}
293+
reformatFiles(project, genVirtualFiles)
294+
openFilesInEditor(project, genVirtualFiles)
296295
}
297296

298297
val finalizers = template.descriptor.finalizers

src/main/kotlin/creator/custom/CustomPlatformStep.kt

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import kotlinx.coroutines.Dispatchers
5656
import kotlinx.coroutines.Job
5757
import kotlinx.coroutines.cancel
5858
import kotlinx.coroutines.launch
59+
import kotlinx.coroutines.withContext
5960

6061
/**
6162
* The step to select a custom template repo.
@@ -219,7 +220,7 @@ class CustomPlatformStep(
219220
val indicator = CreatorProgressIndicator(
220221
templateProvidersLoadingProperty,
221222
templateProvidersTextProperty,
222-
templateProvidersText2Property
223+
templateProvidersText2Property,
223224
)
224225

225226
templateProvidersTextProperty.set(MCDevBundle("creator.step.generic.init_template_providers.message"))
@@ -233,18 +234,24 @@ class CustomPlatformStep(
233234

234235
val dialogCoroutineContext = context.modalityState.asContextElement()
235236
val uiContext = dialogCoroutineContext + Dispatchers.EDT
236-
creatorUiScope.launch(uiContext) {
237-
for ((providerKey, repos) in templateRepos.groupBy { it.provider }) {
238-
val provider = TemplateProvider.get(providerKey)
239-
?: continue
240-
indicator.text = provider.label
241-
runCatching { provider.init(indicator, repos) }
242-
.getOrLogException(logger<CustomPlatformStep>())
237+
creatorUiScope.launch(dialogCoroutineContext) {
238+
// provider.init() downloads/reads files, so run in the background
239+
withContext(Dispatchers.Default) {
240+
for ((providerKey, repos) in templateRepos.groupBy { it.provider }) {
241+
val provider = TemplateProvider.get(providerKey)
242+
?: continue
243+
// indicator.text is a PropertyGraph property, so set it on EDT.
244+
withContext(uiContext) { indicator.text = provider.label }
245+
runCatching { provider.init(indicator, repos) }
246+
.getOrLogException(logger<CustomPlatformStep>())
247+
}
243248
}
244249

245-
templateProvidersLoadingProperty.set(false)
246-
// Force refresh to trigger template loading
247-
templateRepoProperty.set(templateRepo)
250+
withContext(uiContext) {
251+
templateProvidersLoadingProperty.set(false)
252+
// Force refresh to trigger template loading
253+
templateRepoProperty.set(templateRepo)
254+
}
248255
}
249256
}
250257

@@ -263,19 +270,25 @@ class CustomPlatformStep(
263270
val dialogCoroutineContext = context.modalityState.asContextElement()
264271
val uiContext = dialogCoroutineContext + Dispatchers.EDT
265272
templateLoadingJob?.cancel("Another template has been selected")
266-
templateLoadingJob = creatorUiScope.launch(uiContext) {
267-
val newTemplates = runCatching { provider() }
268-
.getOrLogException(logger<CustomPlatformStep>())
269-
?: emptyList()
270-
271-
templateLoadingProperty.set(false)
272-
noTemplatesAvailable.visible(newTemplates.isEmpty())
273-
if (newTemplates.any { checkInvalidVersionTemplate(it) }) {
274-
availableTemplates = emptyList()
275-
invalidTemplateVersion.visible(true)
276-
} else {
277-
availableTemplates = newTemplates
278-
invalidTemplateVersion.visible(false)
273+
templateLoadingJob = creatorUiScope.launch(dialogCoroutineContext) {
274+
// Run slow VFS/IO work on a background thread, not the EDT.
275+
val newTemplates = withContext(Dispatchers.Default) {
276+
runCatching { provider() }
277+
.getOrLogException(logger<CustomPlatformStep>())
278+
?: emptyList()
279+
}
280+
281+
// Switch to EDT only for UI property mutations.
282+
withContext(uiContext) {
283+
templateLoadingProperty.set(false)
284+
noTemplatesAvailable.visible(newTemplates.isEmpty())
285+
if (newTemplates.any { checkInvalidVersionTemplate(it) }) {
286+
availableTemplates = emptyList()
287+
invalidTemplateVersion.visible(true)
288+
} else {
289+
availableTemplates = newTemplates
290+
invalidTemplateVersion.visible(false)
291+
}
279292
}
280293
}
281294
}

src/main/kotlin/creator/custom/providers/TemplateProvider.kt

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import com.intellij.openapi.diagnostic.ControlFlowException
3434
import com.intellij.openapi.diagnostic.thisLogger
3535
import com.intellij.openapi.extensions.ExtensionPointName
3636
import com.intellij.openapi.extensions.RequiredElement
37+
import com.intellij.openapi.progress.ProcessCanceledException
3738
import com.intellij.openapi.progress.ProgressIndicator
3839
import com.intellij.openapi.util.KeyedExtensionCollector
3940
import com.intellij.openapi.vfs.VfsUtilCore
@@ -45,6 +46,7 @@ import com.intellij.serviceContainer.BaseKeyedLazyInstance
4546
import com.intellij.util.KeyedLazyInstance
4647
import com.intellij.util.xmlb.annotations.Attribute
4748
import java.util.ResourceBundle
49+
import java.util.concurrent.CancellationException
4850
import javax.swing.JComponent
4951

5052
/**
@@ -99,7 +101,7 @@ interface TemplateProvider {
99101
createVfsLoadedTemplate(modalityState, file.parent, file, bundle = bundle)
100102
?.let(templates::add)
101103
} catch (t: Throwable) {
102-
if (t is ControlFlowException) {
104+
if (t is ProcessCanceledException || t is ControlFlowException || t is CancellationException) {
103105
throw t
104106
}
105107

@@ -134,7 +136,7 @@ interface TemplateProvider {
134136
languageBundle
135137
)
136138
} catch (t: Throwable) {
137-
if (t is ControlFlowException) {
139+
if (t is ProcessCanceledException || t is ControlFlowException || t is CancellationException) {
138140
throw t
139141
}
140142

@@ -152,9 +154,14 @@ interface TemplateProvider {
152154
}
153155

154156
try {
155-
return file.refreshSync(modalityState)
156-
?.inputStream?.reader()?.use { TemplateResourceBundle(it, parent) }
157+
val refreshedFile = file.refreshSync(modalityState)
158+
if (refreshedFile != null) {
159+
return refreshedFile.inputStream.reader().use { TemplateResourceBundle(it, parent) }
160+
}
157161
} catch (t: Throwable) {
162+
if (t is ProcessCanceledException || t is CancellationException) {
163+
throw t
164+
}
158165
if (t is ControlFlowException) {
159166
return parent
160167
}
@@ -194,7 +201,7 @@ interface TemplateProvider {
194201
if (descriptor.inherit != null) {
195202
val parent = templateRoot.findFileByRelativePath(descriptor.inherit)
196203
if (parent != null) {
197-
parent.refresh(false, false)
204+
parent.refreshSync(modalityState)
198205
val parentDescriptor = Gson().fromJson<TemplateDescriptor>(parent.readText())
199206
val mergedProperties = parentDescriptor.properties.orEmpty() + descriptor.properties.orEmpty()
200207
val mergedFiles = parentDescriptor.files.orEmpty() + descriptor.files.orEmpty()

src/main/kotlin/creator/custom/providers/VfsLoadedTemplate.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,8 @@ open class VfsLoadedTemplate(
3434
) : LoadedTemplate {
3535

3636
override fun loadTemplateContents(path: String): String {
37-
templateRoot.refresh(false, true)
3837
val virtualFile = templateRoot.findFileByRelativePath(path)
3938
?: throw FileNotFoundException("Could not find file $path in template root ${templateRoot.path}")
40-
virtualFile.refresh(false, false)
4139
return virtualFile.readText()
4240
}
4341
}

src/main/kotlin/platform/mixin/handlers/InvokerHandler.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class InvokerHandler : MixinMemberAnnotationHandler {
9191
return "<init>"
9292
}
9393
val name = result.groupValues[2]
94-
if (name.uppercase(Locale.ENGLISH) != name) {
94+
if (name.uppercase(Locale.ENGLISH) != name || name.length == 1) {
9595
return name.decapitalize()
9696
}
9797
return name

0 commit comments

Comments
 (0)