From 1da4ad48174c1bfc83c09788552b01e22bd691dd Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Wed, 8 Apr 2015 11:43:09 +0300 Subject: [PATCH] Resource bundles association algorithm changed: doesn't union property files with non-default languages by automated association. --- plugins/java-i18n/src/META-INF/plugin.xml | 2 +- .../SuspiciousLocalesLanguagesInspection.java | 2 +- .../SuspiciousLanguagesInspectionTest.java | 4 - .../lang/properties/PropertiesUtil.java | 65 +++++++++++-- .../properties/ResourceBundleManager.java | 33 ------- .../psi/impl/PropertiesFileImpl.java | 3 +- .../properties/xml/XmlPropertiesFileImpl.java | 7 +- .../properties/CustomResourceBundleTest.java | 93 ++++++++++++------- .../lang/properties/PropertiesUtilTest.java | 2 +- 9 files changed, 121 insertions(+), 90 deletions(-) diff --git a/plugins/java-i18n/src/META-INF/plugin.xml b/plugins/java-i18n/src/META-INF/plugin.xml index ba0a2ed2eee1..000ddb3400fe 100644 --- a/plugins/java-i18n/src/META-INF/plugin.xml +++ b/plugins/java-i18n/src/META-INF/plugin.xml @@ -57,7 +57,7 @@ diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java index 1dc726b8a2ee..2dda2a31da0b 100644 --- a/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java +++ b/plugins/java-i18n/src/com/intellij/codeInspection/SuspiciousLocalesLanguagesInspection.java @@ -120,7 +120,7 @@ public class SuspiciousLocalesLanguagesInspection extends BaseLocalInspectionToo @Override public Locale fun(PropertiesFile propertiesFile) { final Locale locale = propertiesFile.getLocale(); - return locale == ResourceBundleManager.DEFAULT_LOCALE ? null : locale; + return locale == PropertiesUtil.DEFAULT_LOCALE ? null : locale; } }); bundleLocales = ContainerUtil.filter(bundleLocales, new Condition() { diff --git a/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java b/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java index 891b8fcffe34..04ea10f84e04 100644 --- a/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java +++ b/plugins/java-i18n/testSrc/com/intellij/codeInspection/SuspiciousLanguagesInspectionTest.java @@ -34,10 +34,6 @@ public class SuspiciousLanguagesInspectionTest extends LightCodeInsightFixtureTe doTest("p.properties", "p_en.properties"); } - public void testSimple2() { - doTest("p.properties", "p_asd.properties"); - } - public void testWithAdditionalLocales() { doTest("p.properties", "p_asd.properties", "asd"); } diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java index ac673f634791..ed1d7080705c 100644 --- a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java +++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesUtil.java @@ -16,14 +16,18 @@ package com.intellij.lang.properties; import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; +import com.intellij.reference.SoftLazyValue; +import com.intellij.util.Function; import com.intellij.util.SmartList; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.*; +import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,8 +40,24 @@ import java.util.regex.Pattern; * @author cdr */ public class PropertiesUtil { + private final static Logger LOG = Logger.getInstance(PropertiesUtil.class); + public final static Pattern LOCALE_PATTERN = Pattern.compile("(_[a-zA-Z]{2,8}(_[a-zA-Z]{2}|[0-9]{3})?(_[\\w\\-]+)?)\\.[^_]+$"); - public static final Set BASE_NAME_BORDER_CHAR = ContainerUtil.newHashSet('-', '_', '.'); + public final static Set BASE_NAME_BORDER_CHAR = ContainerUtil.newHashSet('-', '_', '.'); + public final static Locale DEFAULT_LOCALE = new Locale("", "", ""); + + private static final SoftLazyValue> LOCALES_LANGUAGE_CODES = new SoftLazyValue>() { + @NotNull + @Override + protected Set compute() { + return new HashSet(ContainerUtil.map(Locale.getAvailableLocales(), new Function() { + @Override + public String fun(Locale locale) { + return locale.getLanguage(); + } + })); + } + }; /** @@ -87,23 +107,48 @@ public class PropertiesUtil { final Matcher matcher = LOCALE_PATTERN.matcher(name); final String baseNameWithExtension; - if (matcher.find()) { + + int matchIndex = 0; + while (matcher.find(matchIndex)) { final MatchResult matchResult = matcher.toMatchResult(); final String[] splitted = matchResult.group(1).split("_"); if (splitted.length > 1) { + final String langCode = splitted[1]; + if (!LOCALES_LANGUAGE_CODES.getValue().contains(langCode)) { + matchIndex = matchResult.start(1) + 1; + continue; + } baseNameWithExtension = name.substring(0, matchResult.start(1)) + name.substring(matchResult.end(1)); - } - else { - baseNameWithExtension = name; + return FileUtil.getNameWithoutExtension(baseNameWithExtension); } } - else { - baseNameWithExtension = name; - } - + baseNameWithExtension = name; return FileUtil.getNameWithoutExtension(baseNameWithExtension); } + @NotNull + public static Locale getLocale(final @NotNull PropertiesFile propertiesFile) { + String name = propertiesFile.getName(); + if (!StringUtil.containsChar(name, '_')) { + return DEFAULT_LOCALE; + } + final String containingResourceBundleBaseName = propertiesFile.getResourceBundle().getBaseName(); + LOG.assertTrue(name.startsWith(containingResourceBundleBaseName)); + name = name.substring(containingResourceBundleBaseName.length()); + final Matcher matcher = LOCALE_PATTERN.matcher(name); + if (matcher.find()) { + final String rawLocale = matcher.group(1); + final String[] splittedRawLocale = rawLocale.split("_"); + if (splittedRawLocale.length > 1 && splittedRawLocale[1].length() >= 2) { + final String language = splittedRawLocale[1]; + final String country = splittedRawLocale.length > 2 ? splittedRawLocale[2] : ""; + final String variant = splittedRawLocale.length > 3 ? splittedRawLocale[3] : ""; + return new Locale(language, country, variant); + } + } + return DEFAULT_LOCALE; + } + /** * messages_en.properties is a parent of the messages_en_US.properties */ diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java index 318b12048825..0c3cc3649645 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java @@ -47,7 +47,6 @@ import java.util.regex.Matcher; }) public class ResourceBundleManager implements PersistentStateComponent { private final static Logger LOG = Logger.getInstance(ResourceBundleManager.class); - public final static Locale DEFAULT_LOCALE = new Locale("", "", ""); private ResourceBundleManagerState myState = new ResourceBundleManagerState(); @@ -158,38 +157,6 @@ public class ResourceBundleManager implements PersistentStateComponent 1 && splittedRawLocale[1].length() >= 2) { - final String language = splittedRawLocale[1]; - final String country = splittedRawLocale.length > 2 ? splittedRawLocale[2] : ""; - final String variant = splittedRawLocale.length > 3 ? splittedRawLocale[3] : ""; - return new Locale(language, country, variant); - } - } - return DEFAULT_LOCALE; - } - @NotNull public String getBaseName(@NotNull final PsiFile file) { return getBaseName(file.getVirtualFile()); diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java index b839ff919e15..4f19ee31593e 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/psi/impl/PropertiesFileImpl.java @@ -20,7 +20,6 @@ import com.intellij.lang.ASTFactory; import com.intellij.lang.ASTNode; import com.intellij.lang.properties.*; import com.intellij.lang.properties.ResourceBundle; -import com.intellij.lang.properties.ResourceBundleManager; import com.intellij.lang.properties.parsing.PropertiesElementTypes; import com.intellij.lang.properties.psi.PropertiesElementFactory; import com.intellij.lang.properties.psi.PropertiesFile; @@ -136,7 +135,7 @@ public class PropertiesFileImpl extends PsiFileBase implements PropertiesFile { @Override @NotNull public Locale getLocale() { - return ResourceBundleManager.getInstance(getProject()).getLocale(getVirtualFile()); + return PropertiesUtil.getLocale(this); } @Override diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java index 3590681522f8..fd91702bbbfd 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java @@ -17,8 +17,8 @@ package com.intellij.lang.properties.xml; import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.PropertiesImplUtil; +import com.intellij.lang.properties.PropertiesUtil; import com.intellij.lang.properties.ResourceBundle; -import com.intellij.lang.properties.ResourceBundleManager; import com.intellij.lang.properties.psi.PropertiesFile; import com.intellij.lang.properties.psi.Property; import com.intellij.openapi.project.Project; @@ -33,10 +33,7 @@ import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.xml.XmlFile; import com.intellij.psi.xml.XmlTag; import com.intellij.reference.SoftLazyValue; -import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; -import com.intellij.util.SmartList; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; @@ -135,7 +132,7 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile { @NotNull @Override public Locale getLocale() { - return ResourceBundleManager.getInstance(getProject()).getLocale(getVirtualFile()); + return PropertiesUtil.getLocale(this); } @Override diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/CustomResourceBundleTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/CustomResourceBundleTest.java index 69e8621ac8db..1b38908d3dad 100644 --- a/plugins/properties/testSrc/com/intellij/lang/properties/CustomResourceBundleTest.java +++ b/plugins/properties/testSrc/com/intellij/lang/properties/CustomResourceBundleTest.java @@ -26,6 +26,7 @@ import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import java.io.IOException; +import java.util.ArrayList; import java.util.Locale; import static com.intellij.util.containers.ContainerUtil.list; @@ -42,20 +43,62 @@ public class CustomResourceBundleTest extends LightPlatformCodeInsightFixtureTes ResourceBundleManager.getInstance(getProject()).loadState(new ResourceBundleManagerState()); } - public void testDissociateDefaultBaseName() { + public void testPropertiesFilesDefaultCombiningToResourceBundle() { + final PsiFile file = myFixture.addFileToProject("prop_core_en.properties", ""); + final PsiFile file2 = myFixture.addFileToProject("prop_core_fi.properties", ""); + final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file); + final PropertiesFile propertiesFile2 = PropertiesImplUtil.getPropertiesFile(file2); + assertNotNull(propertiesFile); + assertNotNull(propertiesFile2); + final ResourceBundle bundle = propertiesFile.getResourceBundle(); + final ResourceBundle bundle2 = propertiesFile2.getResourceBundle(); + assertTrue(bundle.equals(bundle2)); + assertSize(2, bundle.getPropertiesFiles()); + assertTrue(bundle.getDefaultPropertiesFile().equals(bundle2.getDefaultPropertiesFile())); + assertEquals("prop_core", bundle.getBaseName()); + + assertEquals("English", propertiesFile.getLocale().getDisplayLanguage()); + assertEquals("Finnish", propertiesFile2.getLocale().getDisplayLanguage()); + } + + public void testPropertiesFileNotAssociatedWhileLanguageCodeNotRecognized() { final PsiFile file = myFixture.addFileToProject("some_property_file.properties", ""); - final PsiFile file2 = myFixture.addFileToProject("some_property_filee.properties", ""); + final PsiFile file2 = myFixture.addFileToProject("some_property_fil.properties", ""); final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file); assertNotNull(propertiesFile); final ResourceBundle resourceBundle = propertiesFile.getResourceBundle(); - final ResourceBundleManager resourceBundleBaseNameManager = ResourceBundleManager.getInstance(getProject()); - resourceBundleBaseNameManager.dissociateResourceBundle(resourceBundle); - for (final PsiFile psiFile : list(file, file2)) { - assertEquals(psiFile.getVirtualFile().getNameWithoutExtension(), resourceBundleBaseNameManager.getBaseName(psiFile)); - final PropertiesFile somePropertyFile = PropertiesImplUtil.getPropertiesFile(file); - assertNotNull(somePropertyFile); - assertOneElement(somePropertyFile.getResourceBundle().getPropertiesFiles()); - } + assertSize(1, resourceBundle.getPropertiesFiles()); + + final PropertiesFile propertiesFile2 = PropertiesImplUtil.getPropertiesFile(file2); + assertNotNull(propertiesFile2); + final ResourceBundle resourceBundle2 = propertiesFile.getResourceBundle(); + assertSize(1, resourceBundle2.getPropertiesFiles()); + + assertEquals(PropertiesUtil.DEFAULT_LOCALE, propertiesFile.getLocale()); + } + + public void testLanguageCodeNotRecognized() { + final PsiFile file = myFixture.addFileToProject("p.properties", ""); + final PsiFile file2 = myFixture.addFileToProject("p_asd.properties", ""); + + final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file); + final PropertiesFile propertiesFile2 = PropertiesImplUtil.getPropertiesFile(file2); + assertNotNull(propertiesFile); + assertNotNull(propertiesFile2); + final ResourceBundle bundle = propertiesFile.getResourceBundle(); + final ResourceBundle bundle2 = propertiesFile2.getResourceBundle(); + assertSize(1, bundle.getPropertiesFiles()); + assertSize(1, bundle2.getPropertiesFiles()); + assertEquals("p", bundle.getBaseName()); + assertEquals("p_asd", bundle2.getBaseName()); + + final ResourceBundleManager manager = ResourceBundleManager.getInstance(getProject()); + final ArrayList rawBundle = ContainerUtil.newArrayList(propertiesFile, propertiesFile2); + final String suggestedBaseName = PropertiesUtil.getDefaultBaseName(rawBundle); + assertEquals("p", suggestedBaseName); + manager.combineToResourceBundle(rawBundle, suggestedBaseName); + + assertEquals("asd", propertiesFile2.getLocale().getLanguage()); } public void testCombineToCustomResourceBundleAndDissociateAfter() { @@ -80,8 +123,10 @@ public class CustomResourceBundleTest extends LightPlatformCodeInsightFixtureTes public void testCustomResourceBundleFilesMovedOrDeleted() throws IOException { final PropertiesFile file = PropertiesImplUtil.getPropertiesFile(myFixture.addFileToProject("resources-dev/my-app-dev.properties", "")); - final PropertiesFile file2 = PropertiesImplUtil.getPropertiesFile(myFixture.addFileToProject("resources-dev/my-app-test.properties", "")); - final PropertiesFile file3 = PropertiesImplUtil.getPropertiesFile(myFixture.addFileToProject("resources-prod/my-app-prod.properties", "")); + final PropertiesFile file2 = PropertiesImplUtil.getPropertiesFile( + myFixture.addFileToProject("resources-dev/my-app-test.properties", "")); + final PropertiesFile file3 = PropertiesImplUtil.getPropertiesFile( + myFixture.addFileToProject("resources-prod/my-app-prod.properties", "")); assertNotNull(file); assertNotNull(file2); assertNotNull(file3); @@ -93,7 +138,8 @@ public class CustomResourceBundleTest extends LightPlatformCodeInsightFixtureTes assertSize(3, file.getResourceBundle().getPropertiesFiles()); - final PsiDirectory newDir = PsiManager.getInstance(getProject()).findDirectory(myFixture.getTempDirFixture().findOrCreateDir("new-resources-dir")); + final PsiDirectory newDir = PsiManager.getInstance(getProject()).findDirectory( + myFixture.getTempDirFixture().findOrCreateDir("new-resources-dir")); new MoveFilesOrDirectoriesProcessor(getProject(), new PsiElement[] {file2.getContainingFile()}, newDir, false, false, null, null).run(); file3.getContainingFile().delete(); @@ -105,30 +151,11 @@ public class CustomResourceBundleTest extends LightPlatformCodeInsightFixtureTes assertSize(2, state.getCustomResourceBundles().get(0).getFileUrls()); } - public void testLocaleIfCanExtractFromCustomResourceBundle() { - final PsiFile file = myFixture.addFileToProject("Base_Page.properties", ""); - final PsiFile file2 = myFixture.addFileToProject("Base_Page_en.properties", ""); - final ResourceBundleManager resourceBundleBaseNameManager = ResourceBundleManager.getInstance(getProject()); - final PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file); - assertNotNull(propertiesFile); - resourceBundleBaseNameManager.dissociateResourceBundle(propertiesFile.getResourceBundle()); - resourceBundleBaseNameManager.combineToResourceBundle(map(list(file, file2), new Function() { - @Override - public PropertiesFile fun(final PsiFile psiFile) { - return PropertiesImplUtil.getPropertiesFile(psiFile); - } - }), "Base_Page"); - final PropertiesFile propertiesFile2 = PropertiesImplUtil.getPropertiesFile(file2); - assertNotNull(propertiesFile2); - final Locale locale = propertiesFile2.getLocale(); - assertEquals("en", locale.getLanguage()); - } - public void testSuggestedCustomResourceBundleName() { final PsiFile file = myFixture.addFileToProject("Base_Page.properties", ""); final PsiFile file2 = myFixture.addFileToProject("Base_Page_en.properties", ""); final String baseName = - PropertiesUtil.getDefaultBaseName(ContainerUtil.map(list(file, file2), new Function() { + PropertiesUtil.getDefaultBaseName(map(list(file, file2), new Function() { @Override public PropertiesFile fun(PsiFile psiFile) { return PropertiesImplUtil.getPropertiesFile(file); diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java index 44765f96fc69..44f324781161 100644 --- a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java +++ b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesUtilTest.java @@ -39,7 +39,7 @@ public class PropertiesUtilTest extends LightPlatformCodeInsightFixtureTestCase } public void testBaseNameWithLongLocale() { - assertBaseNameEquals("property_latin.properties", "property"); + assertBaseNameEquals("property_latin.properties", "property_latin"); } public void testBaseNameWithCountryAndVariant() {