Resource bundles association algorithm changed: doesn't union property files with non-default languages by automated association.

This commit is contained in:
Dmitry Batkovich
2015-04-08 11:43:49 +03:00
parent 6ebd2d3d88
commit 1da4ad4817
9 changed files with 121 additions and 90 deletions
+1 -1
View File
@@ -57,7 +57,7 @@
<localInspection language="Properties" shortName="SuspiciousLocalesLanguages"
groupBundle="messages.InspectionsBundle" groupKey="group.names.internationalization.issues"
displayName="Suspicious resource bundle locale languages"
enabledByDefault="true"
enabledByDefault="false"
level="WARNING"
implementationClass="com.intellij.codeInspection.SuspiciousLocalesLanguagesInspection"/>
@@ -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<Locale>() {
@@ -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");
}
@@ -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<Character> BASE_NAME_BORDER_CHAR = ContainerUtil.newHashSet('-', '_', '.');
public final static Set<Character> BASE_NAME_BORDER_CHAR = ContainerUtil.newHashSet('-', '_', '.');
public final static Locale DEFAULT_LOCALE = new Locale("", "", "");
private static final SoftLazyValue<Set<String>> LOCALES_LANGUAGE_CODES = new SoftLazyValue<Set<String>>() {
@NotNull
@Override
protected Set<String> compute() {
return new HashSet<String>(ContainerUtil.map(Locale.getAvailableLocales(), new Function<Locale, String>() {
@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
*/
@@ -47,7 +47,6 @@ import java.util.regex.Matcher;
})
public class ResourceBundleManager implements PersistentStateComponent<ResourceBundleManagerState> {
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<ResourceB
});
}
@NotNull
public Locale getLocale(final @NotNull VirtualFile propertiesFile) {
final String customResourceBundleName = getCustomResourceBundleName(propertiesFile);
String name = propertiesFile.getName();
if (!StringUtil.containsChar(name, '_')) {
return DEFAULT_LOCALE;
}
if (customResourceBundleName != null) {
name = name.substring(customResourceBundleName.length());
}
return extractLocale(name);
}
public static Locale extractLocale(final String suffix) {
final Matcher matcher = PropertiesUtil.LOCALE_PATTERN.matcher(suffix);
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;
}
@NotNull
public String getBaseName(@NotNull final PsiFile file) {
return getBaseName(file.getVirtualFile());
@@ -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
@@ -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
@@ -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<PropertiesFile> 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<PsiFile, PropertiesFile>() {
@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<PsiFile, PropertiesFile>() {
PropertiesUtil.getDefaultBaseName(map(list(file, file2), new Function<PsiFile, PropertiesFile>() {
@Override
public PropertiesFile fun(PsiFile psiFile) {
return PropertiesImplUtil.getPropertiesFile(file);
@@ -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() {