Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Perl-Critic CPAN distribution.

Report information
The Basics
Id: 61970
Status: resolved
Priority: 0/
Queue: Perl-Critic

People
Owner: Nobody in particular
Requestors: rjray [...] blackperl.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 1.109
Fixed in: (no value)



Subject: ValuesAndExpressions::RequireInterpolationOfMetachars false-positives on non-special \-characters
The following line: my $str = '\Q' . join(q{|} => @list) . '\U'; Causes two instances of ValuesAndExpressions::RequireInterpolationOfMetachars to be reported. It seems that the alternative (expressing them as "\\Q" and "\\U") is less clear to the reader. Should this policy only report on instances of '\c' when c is a legitimate special character? (\n, \t, etc.) Randy -- """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" Randy J. Ray Silicon Valley Scale Modelers: http://www.svsm.org rjray@blackperl.com randy.j.ray@gmail.com
On Thu Oct 07 16:16:46 2010, RJRAY wrote: Show quoted text
> The following line: > > my $str = '\Q' . join(q{|} => @list) . '\U'; > > Causes two instances of > ValuesAndExpressions::RequireInterpolationOfMetachars to be reported. It > seems that the alternative (expressing them as "\\Q" and "\\U") is less > clear to the reader. Should this policy only report on instances of '\c' > when c is a legitimate special character? (\n, \t, etc.) > > Randy
Thank you for your report. I sympathize, but the characters you report are, in fact, special in Perl, though they are not in other languages. I quote from 'perldoc perlop': The following escape sequences are available in constructs that interpolate, but not in transliterations. \l lowercase next char \u uppercase next char \L lowercase till \E \U uppercase till \E \E end case modification \Q quote non−word characters till \E For example, $ perl -le 'print "\Ufoo"' prints "FOO". So, just as this policy flags '\n' because it looks like an attempt to interpolate a newline, it flags '\U' because it looks like an attempt to uppercase the rest of the string. I conclude from this that both "\Q" and "\U" should in fact be flagged by this policy, for the same reason that "\n" is. But there are a couple complications. First of all, this policy does _not_ recognize "\l" (lowercase the next character), due to a typo (it checked for "\L" twice), nor does it recognize the \N{...} Unicode names (which appears in 'perlop' a couple paragraphs above the part I cut-and-pasted). As an example of the latter, $ perl -Mcharnames=:full -le 'print "\N{LATIN SMALL LETTER F}"' prints "f". Second, the "\Q" case seems a bit muddled. The document just cited says that "\Q" quotes all non-word characters until "\E". It certainly does in regular expressions. But this means to me that $ perl -le 'print "\Q\n"' should print '\n' (i.e. a back slash followed by a lower-case n). In fact, it prints a back slash followed by two line feeds (one from the -l), with nary an "n" to be found. So resolving "\Q" in a satisfactory manner may involve a ticket to Perl, to find out if the bug is in the code or the documentation (or in my reading of the docs). Tom
Correction: It appears the policy _does_ recognize \N. It does not look for \N{, but this appears not to be necessary. There will definitely be more tests before the dust settles.
After more reading of the perlop documentation (and eventually toke.c in a vain attempt to try to figure out why 'say "\Q\t"' prints a back slash and a tab character instead of a back slash and a 't'), I am still of the opinion that this policy should in fact complain about "\Q" and "\U". A Perl bug has been filed on the behavior of "\Q"; see http://rt.perl.org/rt3/Ticket/Display.html?id=78292 for the gory details. In addition, and to show that the law of unintended consequences is still in full force, I have discovered more back-slashed characters that I believe this policy should detect. "\b" (a backspace) and "\l" ('ell', = lower-case the next character) are documented in perlop, but were omitted from this policy. "\1" ('one') through "\7" (with the same effect as \0 except for their numeric value) are not documented in perlop, but were found in toke.c while I was rummaging through it. All of these have been added to the policy. In another example of the law of unintended consequences, the string '\b' turned up in a couple policies, and so Perl::Critic flunked its self-test. These were fixed by saying "I meant to do that!" (spelled, "## no critic (RequireInterpolationOfMetachars)"). The changes are committed as svn revision 3963.
On Fri Oct 08 17:33:47 2010, WYANT wrote: Show quoted text
> After more reading of the perlop documentation (and eventually toke.c in > a vain attempt to try to figure out why 'say "\Q\t"' prints a back slash > and a tab character instead of a back slash and a 't'), I am still of > the opinion that this policy should in fact complain about "\Q" and > "\U". A Perl bug has been filed on the behavior of "\Q"; see > http://rt.perl.org/rt3/Ticket/Display.html?id=78292 for the gory details.
The Perl bug turned out to be somewhere between the docs and my brain. "abc\Qfoo$bar\Exyz" is the exact equivalent of "abc" . quotemeta( "foo$bar" ) . "xyz".
As a bit of shameless self-promotion, I made myself a Perl::Critic::Policy::ValuesAndExpressions::ProhibitUnknownBackslash which looks for backslashed things which don't have meaning. It only looks at double-quotes by default, which is not the thing at issue in this ticket, but it can be asked for single-quotes too, if you really do want to demand '\\Q' instead of '\Q'. I ended up reckoning a single quote '\X' was often too convenient to object to by default, though might be worthwhile as a matter of personal preference.