Improve UseLocaleWithCaseConversions doc based on #1929

This commit is contained in:
Clément Fournier
2019-07-25 02:41:33 +02:00
parent f269b3dc3f
commit f1fb425313

View File

@ -3421,8 +3421,19 @@ class Test {
class="net.sourceforge.pmd.lang.rule.XPathRule"
externalInfoUrl="${pmd.website.baseurl}/pmd_rules_java_errorprone.html#uselocalewithcaseconversions">
<description>
When doing String.toLowerCase()/toUpperCase() conversions, use Locales to avoids problems with languages that
have unusual conventions, i.e. Turkish.
When doing `String::toLowerCase()/toUpperCase()` conversions, use an explicit locale argument to specify the case transformation rules.
Using `String::toLowerCase()` without arguments implicitly uses `Locale::getDefault()`.
The problem is that the default locale depends on the current JVM setup (and usually on the system in which it is running).
Using the system default may be exactly what you want (e.g. if you are manipulating strings you got through standard input),
but it may as well not be the case (e.g. if you are getting the string over the network or a file, and the encoding is well-defined
and independent of the environment). In the latter case, using the default locale makes the case transformation brittle, as
it may yield unexpected results on a machine whose locale has other case translation rules. For example, in Turkish, the
uppercase form of `i` is `İ` (U+0130, not ASCII) and not `I` (U+0049) as in English.
The rule is intended to *force* developers to think about locales when dealing with strings. By taking a conscious decision about
the choice of locale at the time of writing, you reduce the risk of surprising behaviour down the line, and communicate your intent
to future readers.
</description>
<priority>3</priority>
<properties>
@ -3448,20 +3459,20 @@ PrimarySuffix
</properties>
<example>
<![CDATA[
class Foo {
// BAD
if (x.toLowerCase().equals("list")) { }
// violation - implicitly system-dependent conversion
if (x.toLowerCase().equals("list")) {}
/*
* This will not match "LIST" when in Turkish locale
* The above could be
* if (x.toLowerCase(Locale.US).equals("list")) { }
* or simply
* if (x.equalsIgnoreCase("list")) { }
*/
// GOOD
String z = a.toLowerCase(Locale.EN);
}
// The above will not match "LIST" on a system with a Turkish locale.
// It could be replaced with
if (x.toLowerCase(Locale.US).equals("list")) { }
// or simply
if (x.equalsIgnoreCase("list")) { }
// ok - system independent conversion
String z = a.toLowerCase(Locale.ROOT);
// ok - explicit system-dependent conversion
String z2 = a.toLowerCase(Locale.getDefault());
]]>
</example>
</rule>