IJPL-157848 Disable plugin which language is currently selected, restart should be requested on 'Apply'

GitOrigin-RevId: cc2be41134bf2beb40d98fa8cf06a0cd40c60319
This commit is contained in:
Alexander Lobas
2024-08-06 17:51:51 +02:00
committed by intellij-monorepo-bot
parent 6efdf9aa56
commit c6a02e1e02
4 changed files with 88 additions and 17 deletions

View File

@@ -6943,6 +6943,7 @@ f:com.intellij.ide.plugins.DynamicPlugins
- bs:loadPlugin$default(com.intellij.ide.plugins.DynamicPlugins,com.intellij.ide.plugins.IdeaPluginDescriptorImpl,com.intellij.openapi.project.Project,I,java.lang.Object):Z
- f:loadPlugins(java.util.Collection,com.intellij.openapi.project.Project):Z
- f:onPluginUnload(com.intellij.openapi.Disposable,java.lang.Runnable):V
- f:runAfter(Z,java.lang.Runnable):V
- f:unloadPlugin(com.intellij.ide.plugins.IdeaPluginDescriptorImpl):Z
- f:unloadPlugin(com.intellij.ide.plugins.IdeaPluginDescriptorImpl,com.intellij.ide.plugins.DynamicPlugins$UnloadPluginOptions):Z
- bs:unloadPlugin$default(com.intellij.ide.plugins.DynamicPlugins,com.intellij.ide.plugins.IdeaPluginDescriptorImpl,com.intellij.ide.plugins.DynamicPlugins$UnloadPluginOptions,I,java.lang.Object):Z

View File

@@ -96,6 +96,10 @@ private val LOG = logger<DynamicPlugins>()
private val classloadersFromUnloadedPlugins = mutableMapOf<PluginId, WeakList<PluginClassLoader>>()
object DynamicPlugins {
private var myProcessRun = false
private var myProcessCallback: Runnable? = null
private val myLock = Any()
@JvmStatic
@JvmOverloads
fun allowLoadUnloadWithoutRestart(descriptor: IdeaPluginDescriptorImpl,
@@ -112,8 +116,10 @@ object DynamicPlugins {
* @return true if the requested enabled state was applied without restart, false if restart is required
*/
fun loadPlugins(descriptors: Collection<IdeaPluginDescriptorImpl>, project: Project?): Boolean {
return updateDescriptorsWithoutRestart(descriptors, load = true) {
loadPlugin(it, project)
return runProcess {
updateDescriptorsWithoutRestart(descriptors, load = true) {
doLoadPlugin(it, project)
}
}
}
@@ -126,8 +132,42 @@ object DynamicPlugins {
parentComponent: JComponent? = null,
options: UnloadPluginOptions = UnloadPluginOptions(disable = true),
): Boolean {
return updateDescriptorsWithoutRestart(descriptors, load = false) {
unloadPluginWithProgress(project, parentComponent, it, options)
return runProcess {
updateDescriptorsWithoutRestart(descriptors, load = false) {
doUnloadPluginWithProgress(project, parentComponent, it, options)
}
}
}
private fun runProcess(process: () -> Boolean): Boolean {
try {
synchronized(myLock) {
assert(!myProcessRun)
assert(myProcessCallback == null)
myProcessRun = true
}
return process.invoke()
}
finally {
synchronized(myLock) {
myProcessRun = false
val callback = myProcessCallback
myProcessCallback = null
callback
}?.run()
}
}
fun runAfter(runAlways: Boolean, callback: Runnable) {
synchronized(myLock) {
if (myProcessRun) {
assert(myProcessCallback == null)
myProcessCallback = callback
return
}
}
if (runAlways) {
callback.run()
}
}
@@ -386,6 +426,15 @@ object DynamicPlugins {
parentComponent: JComponent?,
pluginDescriptor: IdeaPluginDescriptorImpl,
options: UnloadPluginOptions): Boolean {
return runProcess {
doUnloadPluginWithProgress(project, parentComponent, pluginDescriptor, options)
}
}
private fun doUnloadPluginWithProgress(project: Project? = null,
parentComponent: JComponent?,
pluginDescriptor: IdeaPluginDescriptorImpl,
options: UnloadPluginOptions): Boolean {
var result = false
if (options.save) {
runInAutoSaveDisabledMode {
@@ -446,7 +495,9 @@ object DynamicPlugins {
@JvmOverloads
fun unloadPlugin(pluginDescriptor: IdeaPluginDescriptorImpl,
options: UnloadPluginOptions = UnloadPluginOptions(disable = true)): Boolean {
return unloadPluginWithProgress(project = null, parentComponent = null, pluginDescriptor, options)
return runProcess {
doUnloadPluginWithProgress(project = null, parentComponent = null, pluginDescriptor, options)
}
}
private fun unloadPluginWithoutProgress(pluginDescriptor: IdeaPluginDescriptorImpl,
@@ -822,6 +873,12 @@ object DynamicPlugins {
@JvmOverloads
fun loadPlugin(pluginDescriptor: IdeaPluginDescriptorImpl, project: Project? = null): Boolean {
return runProcess {
doLoadPlugin(pluginDescriptor, project)
}
}
private fun doLoadPlugin(pluginDescriptor: IdeaPluginDescriptorImpl, project: Project? = null): Boolean {
var result = false
val indicator = PotemkinProgress(IdeBundle.message("plugins.progress.loading.plugin.title", pluginDescriptor.name),
project,

View File

@@ -2,14 +2,20 @@
package com.intellij.ide.plugins
import com.intellij.ide.plugins.LocalizationPluginHelper.isActiveLocalizationPlugin
import com.intellij.ide.ui.LanguageAndRegionUi
import com.intellij.l10n.LocalizationStateService
import com.intellij.openapi.diagnostic.logger
import java.util.Locale
internal class LocalizationPluginListener : DynamicPluginListener {
override fun checkUnloadPlugin(pluginDescriptor: IdeaPluginDescriptor) {
if (isActiveLocalizationPlugin(pluginDescriptor)) {
logger<LocalizationPluginListener>().debug("throw CannotUnloadPluginException during unload Localization plugin")
throw CannotUnloadPluginException("Localization plugin ${pluginDescriptor.pluginId} cannot be dynamically unloaded because it's selected language")
logger<LocalizationPluginListener>().info("[i18n] Language setting was reset to default during unload Localization plugin")
LocalizationStateService.getInstance()?.setSelectedLocale(Locale.ENGLISH.toLanguageTag())
LanguageAndRegionUi.showRestartDialog(false)
}
}
}

View File

@@ -8,6 +8,7 @@ import com.intellij.ide.IdeBundle
import com.intellij.ide.Region
import com.intellij.ide.RegionSettings
import com.intellij.ide.RegionSettings.RegionSettingsListener
import com.intellij.ide.plugins.DynamicPlugins
import com.intellij.ide.plugins.PluginManagerConfigurable
import com.intellij.ide.ui.localization.statistics.EventSource
import com.intellij.ide.ui.localization.statistics.LocalizationActionsStatistics
@@ -76,9 +77,7 @@ class LanguageAndRegionUi {
localizationService.setSelectedLocale(it.toLanguageTag())
application.invokeLater {
application.service<RestartDialog>().showRestartRequired()
}
showRestartDialog()
}
languageBox.bindItem(property)
@@ -127,8 +126,12 @@ class LanguageAndRegionUi {
private fun updateComboModel() {
val newLocales = getAllAvailableLocales()
var selection = languageComponent.selectedItem as Locale
if (!newLocales.first.contains(selection)) {
selection = newLocales.first.first()
}
languageComponent.renderer = LanguageComboBoxRenderer(newLocales)
languageComponent.model = CollectionComboBoxModel(newLocales.first, languageComponent.selectedItem as Locale)
languageComponent.model = CollectionComboBoxModel(newLocales.first, selection)
}
}, parentDisposable)
}
@@ -149,9 +152,7 @@ class LanguageAndRegionUi {
RegionSettings.setRegion(it)
application.invokeLater {
application.service<RestartDialog>().showRestartRequired()
}
showRestartDialog()
}
regionBox.bindItem(property)
@@ -193,6 +194,14 @@ class LanguageAndRegionUi {
}
}
fun showRestartDialog(runAlways: Boolean = true) {
DynamicPlugins.runAfter(runAlways) {
application.invokeLater {
application.service<RestartDialog>().showRestartRequired()
}
}
}
private fun getAllAvailableLocales(): Pair<List<Locale>, Map<Locale, String>> {
val availableLocales = LocalizationUtil.getAllAvailableLocales()
return buildList {
@@ -240,9 +249,7 @@ internal class LanguageAndRegionConfigurable :
if (initSelectionLanguage.toLanguageTag() != selectedLocale.toLanguageTag() ||
initSelectionRegion != selectedRegion) {
LocalizationActionsStatistics().apply { setSource(eventSource) }.settingsUpdated(selectedLocale, initSelectionLanguage, selectedRegion, initSelectionRegion)
application.invokeLater {
application.service<RestartDialog>().showRestartRequired()
}
LanguageAndRegionUi.showRestartDialog()
}
}
}