From 11178787f75721b8a5c2ebe81f7d432526f9d245 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Tue, 17 Dec 2019 01:58:45 +0300 Subject: [PATCH] introduce DynamicBundle and LanguageBundle EP language bundle allows to load localized resources via plugin machinery GitOrigin-RevId: c2dca049a840b7c0b79ac372f42631bd0e496a83 --- .../codeInsight/daemon/JavaErrorMessages.java | 4 +- .../lang/manifest/ManifestBundle.java | 4 +- .../intellij/analysis/JvmAnalysisBundle.java | 4 +- .../intention/IntentionActionBean.java | 4 +- .../intellij/codeInspection/InspectionEP.java | 4 +- .../src/ExportSettingsAction.kt | 4 +- platform/core-api/resources/META-INF/Core.xml | 1 + .../src/com/intellij/DynamicBundle.java | 57 +++++++++++++++++++ .../src/com/intellij/ide/IdeBundle.java | 4 +- .../com/intellij/openapi/vfs/VfsBundle.java | 4 +- .../ide/plugins/IdeaPluginDescriptorImpl.java | 4 +- .../util/ExternalSystemBundle.java | 4 +- .../intellij/execution/ExecutionBundle.java | 3 +- .../template/impl/TemplateSettings.java | 4 +- .../integration/LocalHistoryBundle.java | 4 +- .../src/com/intellij/ide/TypeNameEP.java | 4 +- .../openapi/options/ConfigurableEP.java | 4 +- .../internal/statistic/StatisticsBundle.java | 4 +- .../actionSystem/impl/ActionManagerImpl.java | 4 +- .../util/src/com/intellij/AbstractBundle.java | 8 ++- .../plugins/intelliLang/IntelliLangBundle.kt | 4 +- .../devkit/devkit-core/src/DevKitBundle.java | 4 +- .../plugins/gradle/util/GradleBundle.java | 4 +- .../util/GradleDocumentationBundle.java | 4 +- .../java/decompiler/IdeaDecompilerBundle.kt | 4 +- .../idea/maven/execution/RunnerBundle.java | 3 +- .../idea/maven/execution/SyncBundle.java | 3 +- .../completion/StatsCollectorBundle.java | 3 +- .../codeInsight/daemon/XmlErrorMessages.java | 4 +- 29 files changed, 116 insertions(+), 50 deletions(-) create mode 100644 platform/core-api/src/com/intellij/DynamicBundle.java diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/daemon/JavaErrorMessages.java b/java/java-psi-impl/src/com/intellij/codeInsight/daemon/JavaErrorMessages.java index 755346cde7f0..633c8bfa35d3 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/daemon/JavaErrorMessages.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/daemon/JavaErrorMessages.java @@ -15,7 +15,7 @@ */ package com.intellij.codeInsight.daemon; -import com.intellij.AbstractBundle; +import com.intellij.DynamicBundle; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.PropertyKey; @@ -23,7 +23,7 @@ import org.jetbrains.annotations.PropertyKey; /** * @author max */ -public class JavaErrorMessages extends AbstractBundle { +public class JavaErrorMessages extends DynamicBundle { @NotNull public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) { diff --git a/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java b/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java index 7b9ba1d92f5c..1e4021628617 100644 --- a/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java +++ b/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java @@ -15,11 +15,11 @@ */ package org.jetbrains.lang.manifest; -import com.intellij.AbstractBundle; +import com.intellij.DynamicBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.PropertyKey; -public class ManifestBundle extends AbstractBundle { +public class ManifestBundle extends DynamicBundle { public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) { return BUNDLE.getMessage(key, params); diff --git a/jvm/jvm-analysis-impl/src/com/intellij/analysis/JvmAnalysisBundle.java b/jvm/jvm-analysis-impl/src/com/intellij/analysis/JvmAnalysisBundle.java index daf9c4eac854..deb27d5cf904 100644 --- a/jvm/jvm-analysis-impl/src/com/intellij/analysis/JvmAnalysisBundle.java +++ b/jvm/jvm-analysis-impl/src/com/intellij/analysis/JvmAnalysisBundle.java @@ -1,12 +1,12 @@ // Copyright 2000-2018 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.analysis; -import com.intellij.AbstractBundle; +import com.intellij.DynamicBundle; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.PropertyKey; -public class JvmAnalysisBundle extends AbstractBundle { +public class JvmAnalysisBundle extends DynamicBundle { public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) { return ourInstance.getMessage(key, params); } diff --git a/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionActionBean.java b/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionActionBean.java index 00558212d8a6..7e003c552015 100644 --- a/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionActionBean.java +++ b/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionActionBean.java @@ -1,8 +1,8 @@ // Copyright 2000-2019 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.codeInsight.intention; -import com.intellij.AbstractBundle; import com.intellij.CommonBundle; +import com.intellij.DynamicBundle; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.CustomLoadingExtensionPointBean; import com.intellij.util.containers.ContainerUtil; @@ -47,7 +47,7 @@ public final class IntentionActionBean extends CustomLoadingExtensionPointBean 1) { diff --git a/platform/analysis-api/src/com/intellij/codeInspection/InspectionEP.java b/platform/analysis-api/src/com/intellij/codeInspection/InspectionEP.java index 1210418ed101..caa2c5e675a8 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/InspectionEP.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/InspectionEP.java @@ -1,8 +1,8 @@ // Copyright 2000-2019 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.codeInspection; -import com.intellij.AbstractBundle; import com.intellij.CommonBundle; +import com.intellij.DynamicBundle; import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.diagnostic.PluginException; import com.intellij.lang.Language; @@ -189,7 +189,7 @@ public class InspectionEP extends LanguageExtensionPoint } return null; } - ResourceBundle resourceBundle = AbstractBundle.getResourceBundle(baseName, getLoaderForClass()); + ResourceBundle resourceBundle = DynamicBundle.INSTANCE.getResourceBundle(baseName, getLoaderForClass()); return CommonBundle.message(resourceBundle, key); } diff --git a/platform/configuration-store-impl/src/ExportSettingsAction.kt b/platform/configuration-store-impl/src/ExportSettingsAction.kt index 6d2c0c5b1765..26c5d052b6a1 100644 --- a/platform/configuration-store-impl/src/ExportSettingsAction.kt +++ b/platform/configuration-store-impl/src/ExportSettingsAction.kt @@ -1,8 +1,8 @@ // Copyright 2000-2019 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.configurationStore -import com.intellij.AbstractBundle import com.intellij.CommonBundle +import com.intellij.DynamicBundle import com.intellij.configurationStore.schemeManager.ROOT_CONFIG import com.intellij.configurationStore.schemeManager.SchemeManagerFactoryBase import com.intellij.ide.IdeBundle @@ -293,7 +293,7 @@ private fun getComponentPresentableName(state: State, aClass: Class<*>, pluginDe private fun messageOrDefault(classLoader: ClassLoader, bundleName: String, defaultName: String): String { try { return CommonBundle.messageOrDefault( - AbstractBundle.getResourceBundle(bundleName, classLoader), "exportable.$defaultName.presentable.name", defaultName) + DynamicBundle.INSTANCE.getResourceBundle(bundleName, classLoader), "exportable.$defaultName.presentable.name", defaultName) } catch (e: MissingResourceException) { LOG.warn("Missing bundle ${bundleName} at ${classLoader}: ${e.message}") diff --git a/platform/core-api/resources/META-INF/Core.xml b/platform/core-api/resources/META-INF/Core.xml index 4faee323d79f..0b1995d9b5a6 100644 --- a/platform/core-api/resources/META-INF/Core.xml +++ b/platform/core-api/resources/META-INF/Core.xml @@ -1,5 +1,6 @@ + diff --git a/platform/core-api/src/com/intellij/DynamicBundle.java b/platform/core-api/src/com/intellij/DynamicBundle.java new file mode 100644 index 000000000000..b4e16592d86b --- /dev/null +++ b/platform/core-api/src/com/intellij/DynamicBundle.java @@ -0,0 +1,57 @@ +// Copyright 2000-2019 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; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.AbstractExtensionPointBean; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.util.ReflectionUtil; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Method; +import java.util.ResourceBundle; + +public abstract class DynamicBundle extends AbstractBundle { + private final static Logger LOG = Logger.getInstance(DynamicBundle.class); + private final static Method SET_PARENT = ReflectionUtil.getDeclaredMethod(ResourceBundle.class, "setParent", ResourceBundle.class); + + protected DynamicBundle(@NotNull String pathToBundle) { + super(pathToBundle); + } + + @Override + protected ResourceBundle findBundle(@NotNull String pathToBundle, + @NotNull ClassLoader baseLoader, + @NotNull ResourceBundle.Control control) { + ResourceBundle base = super.findBundle(pathToBundle, baseLoader, control); + + LanguageBundleEP langBundle = findLanguageBundle(); + if (langBundle == null) return base; + + ResourceBundle pluginBundle = super.findBundle(pathToBundle, langBundle.getLoaderForClass(), control); + if (pluginBundle == null) return base; + + try { + if (SET_PARENT != null) { + SET_PARENT.invoke(pluginBundle, base); + } + } + catch (Exception e) { + LOG.warn(e); + } + return pluginBundle; + } + + // todo: one language per application + private static LanguageBundleEP findLanguageBundle() { + return LanguageBundleEP.EP_NAME.findExtension(LanguageBundleEP.class); + } + + public static final DynamicBundle INSTANCE = new DynamicBundle("") { + }; + + public static class LanguageBundleEP extends AbstractExtensionPointBean { + public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.languageBundle"); + } +} + + diff --git a/platform/core-api/src/com/intellij/ide/IdeBundle.java b/platform/core-api/src/com/intellij/ide/IdeBundle.java index a520bb47183a..a43805bab0b2 100644 --- a/platform/core-api/src/com/intellij/ide/IdeBundle.java +++ b/platform/core-api/src/com/intellij/ide/IdeBundle.java @@ -15,14 +15,14 @@ */ package com.intellij.ide; -import com.intellij.AbstractBundle; +import com.intellij.DynamicBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.PropertyKey; /** * @author yole */ -public class IdeBundle extends AbstractBundle { +public class IdeBundle extends DynamicBundle { public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) { return INSTANCE.getMessage(key, params); } diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsBundle.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsBundle.java index d7e4ab8acd4b..0f5117c840a2 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/VfsBundle.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsBundle.java @@ -16,7 +16,7 @@ package com.intellij.openapi.vfs; -import com.intellij.AbstractBundle; +import com.intellij.DynamicBundle; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.PropertyKey; @@ -24,7 +24,7 @@ import org.jetbrains.annotations.PropertyKey; /** * @author yole */ -public class VfsBundle extends AbstractBundle { +public class VfsBundle extends DynamicBundle { public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) { return ourInstance.getMessage(key, params); diff --git a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java index 264062c2e1ac..0b63d250bc9c 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java @@ -1,8 +1,8 @@ // Copyright 2000-2019 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.ide.plugins; -import com.intellij.AbstractBundle; import com.intellij.CommonBundle; +import com.intellij.DynamicBundle; import com.intellij.diagnostic.PluginException; import com.intellij.openapi.components.ComponentConfig; import com.intellij.openapi.components.ComponentManager; @@ -642,7 +642,7 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor, Plu ResourceBundle bundle = null; if (myResourceBundleBaseName != null) { try { - bundle = AbstractBundle.getResourceBundle(myResourceBundleBaseName, getPluginClassLoader()); + bundle = DynamicBundle.INSTANCE.getResourceBundle(myResourceBundleBaseName, getPluginClassLoader()); } catch (MissingResourceException e) { LOG.info("Cannot find plugin " + myId + " resource-bundle: " + myResourceBundleBaseName); diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemBundle.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemBundle.java index 3df3e60239ea..eae9541e0341 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemBundle.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemBundle.java @@ -15,14 +15,14 @@ */ package com.intellij.openapi.externalSystem.util; -import com.intellij.AbstractBundle; +import com.intellij.DynamicBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.PropertyKey; /** * @author Denis Zhdanov */ -public class ExternalSystemBundle extends AbstractBundle { +public class ExternalSystemBundle extends DynamicBundle { public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) { return BUNDLE.getMessage(key, params); diff --git a/platform/lang-api/src/com/intellij/execution/ExecutionBundle.java b/platform/lang-api/src/com/intellij/execution/ExecutionBundle.java index 42db1a45147f..e4222b8f1d67 100644 --- a/platform/lang-api/src/com/intellij/execution/ExecutionBundle.java +++ b/platform/lang-api/src/com/intellij/execution/ExecutionBundle.java @@ -2,13 +2,14 @@ package com.intellij.execution; import com.intellij.AbstractBundle; +import com.intellij.DynamicBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.PropertyKey; /** * @author lesya */ -public class ExecutionBundle extends AbstractBundle { +public class ExecutionBundle extends DynamicBundle { @NotNull public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) { return ourInstance.getMessage(key, params); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java index 1f35e641701d..9ebdd62caa67 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java @@ -1,7 +1,7 @@ // Copyright 2000-2019 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.codeInsight.template.impl; -import com.intellij.AbstractBundle; +import com.intellij.DynamicBundle; import com.intellij.codeInsight.template.Macro; import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateContextType; @@ -640,7 +640,7 @@ public final class TemplateSettings implements PersistentStateComponent