diff --git a/platform/util/src/com/intellij/openapi/util/text/Pluralizer.java b/platform/util/src/com/intellij/openapi/util/text/Pluralizer.java index adb247078af2..30a9e1bf3866 100644 --- a/platform/util/src/com/intellij/openapi/util/text/Pluralizer.java +++ b/platform/util/src/com/intellij/openapi/util/text/Pluralizer.java @@ -30,6 +30,7 @@ import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.JBIterable; import com.intellij.util.text.CaseInsensitiveStringHashingStrategy; +import org.jetbrains.annotations.Nullable; import java.util.List; import java.util.Map; @@ -37,6 +38,8 @@ import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; +import static com.intellij.openapi.util.text.StringUtil.notNullize; + /** * A java version of http://github.com/blakeembrey/pluralize * Revision: 90d82f88428f057c4b7a1d46aa38fc7c44d2d869 @@ -98,11 +101,12 @@ class Pluralizer { return matcher.replaceFirst(rule.second); } } - return word; + return null; } /** * Replace a word with the updated word. + * @return null if no applicable rules found */ private String replaceWord(String word, Map replaceMap, Map keepMap, List> rules) { if (StringUtil.isEmpty(word)) return word; @@ -112,8 +116,9 @@ class Pluralizer { if (keepMap.containsKey(word)) return word; // Check against the replacement map for a direct word replacement. - if (replaceMap.containsKey(word)) { - return restoreCase(word, replaceMap.get(word)); + String replacement = replaceMap.get(word); + if (replacement != null) { + return replacement; } // Run all the rules against the word. @@ -126,14 +131,16 @@ class Pluralizer { public String pluralize(String word, int count, boolean inclusive) { String pluralized = count == 1 ? singular(word) : plural(word); - return (inclusive ? count + " " : "") + pluralized; + return (inclusive ? count + " " : "") + notNullize(pluralized, word); } - public String plural(String word) { + @Nullable + public String plural(@Nullable String word) { return restoreCase(word, replaceWord(word, irregularSingles, irregularPlurals, pluralRules)); } - public String singular(String word) { + @Nullable + public String singular(@Nullable String word) { return restoreCase(word, replaceWord(word, irregularPlurals, irregularSingles, singularRules)); } @@ -258,7 +265,6 @@ class Pluralizer { {"/(child)(?:ren)?$", "$1ren"}, {"/eaux$", "$0"}, {"/m[ae]n$", "men"}, - {"thou", "you"} }).consumeEach(new Consumer() { @Override public void consume(String[] o) { @@ -271,7 +277,7 @@ class Pluralizer { */ JBIterable.of(new String[][]{ {"/(.)s$", "$1"}, - {"/(ss)$", "$1"}, + {"/([^aeiou]s)es$", "$1"}, {"/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(?:sis|ses)$", "$1sis"}, {"/(^analy)(?:sis|ses)$", "$1sis"}, {"/(wi|kni|(?:after|half|high|low|mid|non|night|[^\\w]|^)li)ves$", "$1fe"}, @@ -281,7 +287,7 @@ class Pluralizer { {"/\\b(mon|smil)ies$", "$1ey"}, {"/(m|l)ice$", "$1ouse"}, {"/(seraph|cherub)im$", "$1"}, - {"/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|tlas|gas|(?:her|at|gr)o|ris)(?:es)?$", "$1"}, + {"/(x|ch|.ss|sh|zz|tto|go|cho|alias|[^aou]us|tlas|gas|(?:her|at|gr)o|ris)(?:es)?$", "$1"}, {"/(e[mn]u)s?$", "$1"}, {"/(cookie|movie|twelve)s$", "$1"}, {"/(cris|test|diagnos)(?:is|es)$", "$1is"}, diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 80de7a697048..518a150bd21a 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -830,8 +830,9 @@ public class StringUtil extends StringUtilRt { @Contract(pure = true) public static String pluralize(@NotNull String word) { String plural = Pluralizer.PLURALIZER.plural(word); - return equalsIgnoreCase(plural, word) && !endsWithIgnoreCase(plural, "es") ? - Pluralizer.restoreCase(word, word + "s") : plural; + if (plural != null) return plural; + if (word.endsWith("s")) return Pluralizer.restoreCase(word, word + "es"); + return Pluralizer.restoreCase(word, word + "s"); } @NotNull @@ -1647,10 +1648,10 @@ public class StringUtil extends StringUtilRt { @Contract(pure = true) public static String unpluralize(@NotNull String word) { String singular = Pluralizer.PLURALIZER.singular(word); - if (equalsIgnoreCase(singular, word)) { - singular = nullize(trimEnd(singular, "s", true)); - } - return equalsIgnoreCase(singular, word) ? null : singular; + if (singular != null) return singular; + if (word.endsWith("es")) return nullize(trimEnd(word, "es", true)); + if (word.endsWith("s")) return nullize(trimEnd(word, "s", true)); + return null; } @Contract(pure = true) diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java index e4d7f69bf81e..68020f91fe89 100644 --- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java @@ -98,16 +98,22 @@ public class StringUtilTest { @Test public void testUnPluralize() { - assertEquals("plurals", StringUtil.unpluralize("pluralss")); + // synthetic + assertEquals("plurals", StringUtil.unpluralize("pluralses")); + assertEquals("Inherits", StringUtil.unpluralize("Inheritses")); + assertEquals("s", StringUtil.unpluralize("ss")); assertEquals("I", StringUtil.unpluralize("Is")); assertEquals(null, StringUtil.unpluralize("s")); assertEquals("z", StringUtil.unpluralize("zs")); + // normal + assertEquals("case", StringUtil.unpluralize("cases")); assertEquals("Index", StringUtil.unpluralize("Indices")); assertEquals("fix", StringUtil.unpluralize("fixes")); assertEquals("man", StringUtil.unpluralize("men")); assertEquals("leaf", StringUtil.unpluralize("leaves")); assertEquals("cookie", StringUtil.unpluralize("cookies")); assertEquals("search", StringUtil.unpluralize("searches")); + assertEquals("process", StringUtil.unpluralize("process")); } @Test