IJPL-15953 soft-assert write action in LanguageLevelProjectExtension.{setLanguageLevel and setDefault} methods

GitOrigin-RevId: 9962ba7183e10272cbca2f4511f66a34be067fb4
This commit is contained in:
Andrei.Kuznetsov
2025-08-05 18:43:11 +02:00
committed by intellij-monorepo-bot
parent 93d4213af7
commit 8712a254f3
6 changed files with 52 additions and 15 deletions

View File

@@ -3,6 +3,7 @@ package com.intellij.ide.projectWizard;
import com.intellij.ide.projectWizard.generators.IntelliJJavaNewProjectWizardData;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
@@ -123,8 +124,10 @@ public class NewProjectWizardTest extends NewProjectWizardTestCase {
public void testMigrateFromOldDefaults() throws Exception {
LanguageLevelProjectExtension defaultExt = LanguageLevelProjectExtension.getInstance(ProjectManager.getInstance().getDefaultProject());
defaultExt.setLanguageLevel(LanguageLevel.JDK_1_4);
defaultExt.setDefault(null); // emulate migration from previous build
WriteAction.run(() -> {
defaultExt.setLanguageLevel(LanguageLevel.JDK_1_4);
defaultExt.setDefault(null); // emulate migration from previous build
});
Project project = createProjectFromTemplate(JAVA, step -> {});
LanguageLevelProjectExtension extension = LanguageLevelProjectExtension.getInstance(project);
@@ -164,17 +167,22 @@ public class NewProjectWizardTest extends NewProjectWizardTestCase {
ProjectManager projectManager = ProjectManager.getInstance();
Project defaultProject = projectManager.getDefaultProject();
LanguageLevel old = LanguageLevelProjectExtension.getInstance(defaultProject).getLanguageLevel();
LanguageLevelProjectExtension languageLevelProjectExtension = LanguageLevelProjectExtension.getInstance(defaultProject);
LanguageLevel old = languageLevelProjectExtension.getLanguageLevel();
try {
LanguageLevelProjectExtension.getInstance(defaultProject).setLanguageLevel(languageLevel);
LanguageLevelProjectExtension.getInstance(defaultProject).setDefault(detect);
WriteAction.run(() -> {
languageLevelProjectExtension.setLanguageLevel(languageLevel);
languageLevelProjectExtension.setDefault(detect);
});
Project project = createProjectFromTemplate(JAVA, step -> {});
assertEquals(languageLevel, LanguageLevelProjectExtension.getInstance(project).getLanguageLevel());
return project;
}
finally {
LanguageLevelProjectExtension.getInstance(defaultProject).setLanguageLevel(old);
LanguageLevelProjectExtension.getInstance(defaultProject).setDefault(true);
WriteAction.run(() -> {
languageLevelProjectExtension.setLanguageLevel(old);
languageLevelProjectExtension.setDefault(true);
});
}
}

View File

@@ -3,6 +3,7 @@ package com.intellij.openapi.roots;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.util.concurrency.annotations.RequiresWriteLock;
import com.intellij.util.messages.Topic;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -24,6 +25,7 @@ public abstract class LanguageLevelProjectExtension {
*/
public abstract @NotNull LanguageLevel getLanguageLevel();
@RequiresWriteLock
public abstract void setLanguageLevel(@NotNull LanguageLevel languageLevel);
/**
@@ -32,6 +34,7 @@ public abstract class LanguageLevelProjectExtension {
*/
public abstract @Nullable Boolean getDefault();
@RequiresWriteLock
public abstract void setDefault(@Nullable Boolean value);
public boolean isDefault() {

View File

@@ -1,6 +1,8 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.roots.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
@@ -11,6 +13,7 @@ import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.pom.java.JavaRelease;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.util.ObjectUtils;
import com.intellij.util.concurrency.annotations.RequiresWriteLock;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -24,6 +27,7 @@ import java.util.Objects;
public final class LanguageLevelProjectExtensionImpl extends LanguageLevelProjectExtension {
private static final String LANGUAGE_LEVEL = "languageLevel";
private static final String DEFAULT_ATTRIBUTE = "default";
private static final Logger LOG = Logger.getInstance(LanguageLevelProjectExtensionImpl.class);
private final Project myProject;
private @Nullable LanguageLevel myLanguageLevel;
@@ -32,7 +36,6 @@ public final class LanguageLevelProjectExtensionImpl extends LanguageLevelProjec
public LanguageLevelProjectExtensionImpl(final Project project) {
myProject = project;
setDefault(project.isDefault() ? true : null);
}
public static LanguageLevelProjectExtensionImpl getInstanceImpl(Project project) {
@@ -54,7 +57,7 @@ public final class LanguageLevelProjectExtensionImpl extends LanguageLevelProjec
String aDefault = element.getAttributeValue(DEFAULT_ATTRIBUTE);
Boolean defaultOldValue = getDefault();
if (aDefault != null) {
setDefault(Boolean.parseBoolean(aDefault));
myDefault = Boolean.parseBoolean(aDefault);
}
return !Objects.equals(defaultOldValue, getDefault()) || languageLevelOldValue != myLanguageLevel;
}
@@ -89,7 +92,12 @@ public final class LanguageLevelProjectExtensionImpl extends LanguageLevelProjec
}
@Override
@RequiresWriteLock(generateAssertion = false)
public void setLanguageLevel(@NotNull LanguageLevel languageLevel) {
LOG.assertTrue(ApplicationManager.getApplication().isWriteAccessAllowed(),
"Language level may only be updated under write action. " +
"Please acquire write action before invoking setLanguageLevel.");
// we don't use here getLanguageLevelOrDefault() - if null, just set to provided value because our default (JavaRelease.getHighest())
// is changed every java release
if (myLanguageLevel != languageLevel) {
@@ -105,7 +113,12 @@ public final class LanguageLevelProjectExtensionImpl extends LanguageLevelProjec
}
@Override
@RequiresWriteLock(generateAssertion = false)
public void setDefault(@Nullable Boolean newDefault) {
LOG.assertTrue(ApplicationManager.getApplication().isWriteAccessAllowed(),
"Language level may only be updated under write action. " +
"Please acquire write action before invoking setDefault.");
myDefault = newDefault;
}

View File

@@ -1,6 +1,7 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.roots.ui.configuration;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
@@ -51,8 +52,10 @@ public class LanguageLevelComboTest extends LightPlatformTestCase {
public void testPreserveLanguageLevel() {
LanguageLevelProjectExtension extension = LanguageLevelProjectExtension.getInstance(myProject);
extension.setDefault(false);
extension.setLanguageLevel(LanguageLevel.JDK_1_5);
WriteAction.run(() -> {
extension.setDefault(false);
extension.setLanguageLevel(LanguageLevel.JDK_1_5);
});
myCombo.reset(myProject);
myCombo.sdkUpdated(IdeaTestUtil.getMockJdk17(), false);

View File

@@ -57,15 +57,20 @@ public final class IdeaTestUtil {
final LanguageLevel projectLevel = projectExt.getLanguageLevel();
final LanguageLevel moduleLevel = LanguageLevelUtil.getCustomLanguageLevel(module);
final Application application = ApplicationManager.getApplication();
try {
projectExt.setLanguageLevel(level);
application.invokeAndWait(() -> {
application.runWriteAction(() -> projectExt.setLanguageLevel(level));
});
setModuleLanguageLevel(module, level);
IndexingTestUtil.waitUntilIndexesAreReady(module.getProject());
r.run();
}
finally {
setModuleLanguageLevel(module, moduleLevel);
projectExt.setLanguageLevel(projectLevel);
application.invokeAndWait(() -> {
application.runWriteAction(() -> projectExt.setLanguageLevel(projectLevel));
});
IndexingTestUtil.waitUntilIndexesAreReady(module.getProject());
}
}
@@ -80,7 +85,10 @@ public final class IdeaTestUtil {
public static LanguageLevel setProjectLanguageLevel(@NotNull Project project, @NotNull LanguageLevel level) {
LanguageLevelProjectExtension projectExt = LanguageLevelProjectExtension.getInstance(project);
LanguageLevel oldLevel = projectExt.getLanguageLevel();
projectExt.setLanguageLevel(level);
Application application = ApplicationManager.getApplication();
application.invokeAndWait(() -> {
application.runWriteAction(() -> projectExt.setLanguageLevel(level));
});
IndexingTestUtil.waitUntilIndexesAreReady(project);
return oldLevel;
}

View File

@@ -2,6 +2,7 @@
package com.intellij.codeInspection.i18n;
import com.intellij.lang.properties.UnsupportedCharacterInspection;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.encoding.EncodingManager;
@@ -186,7 +187,8 @@ public class UnsupportedCharacterInspectionTest extends JavaCodeInsightFixtureTe
}
private void javaVersion(LanguageLevel jdk) {
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(jdk);
var ext = LanguageLevelProjectExtension.getInstance(getProject());
WriteAction.run(() -> ext.setLanguageLevel(jdk));
}
private static void fileEncoding(PsiFile file, Charset charset) {