#-----------------------------------------------------------------------------
-# The following regex should be "qr{^ [^\t]+ \t}xms"
-# but it doesn't match when I expect it to. I
-# haven't figured out why. So I used [^\s]
-# as a substitue to mean "not a tab".
+# The following regex should probably be "qr{^ .* [^\t]+ \t}xms" but it doesn't
+# match when I expect it to. I haven't figured out why, so I used "\S" to
+# approximately mean "not a tab", and that seemd to work.
-my $NON_LEADING_TAB_REGEX = qr{^ [^\s]+ \t}xms;
+my $NON_LEADING_TAB_REGEX = qr{^ .* \S+ \t }xms;
#-----------------------------------------------------------------------------
# The __DATA__ element is exempt
return if $elem->parent->isa('PPI::Statement::Data');
- # Permit leading tabs, if allowed
- return if $self->_allow_leading_tabs() && $elem !~ $NON_LEADING_TAB_REGEX;
-
- # Must be a violation...
+ # If allowed, permit leading tabs in situations where whitespace s not significant.
+ if ( $self->_allow_leading_tabs() ) {
+
+ return if $elem->location->[1] == 1;
+
+ return if _is_extended_regex($elem)
+ && $elem !~ $NON_LEADING_TAB_REGEX;
+
+ return if $elem->isa('PPI::Token::QuoteLike::Words')
+ && $elem !~ $NON_LEADING_TAB_REGEX;
+ }
+
+ # If we get here, then it must be a violation...
return $self->violation( $DESC, $EXPL, $elem );
}
sub _allow_leading_tabs {
my ( $self ) = @_;
-
return $self->{_allow_leading_tabs};
}
+#-----------------------------------------------------------------------------
+
+sub _is_extended_regex {
+ my ($elem) = @_;
+
+ $elem->isa('PPI::Token::Regexp')
+ || $elem->isa('PPI::Token::QuoteLike::Regexp')
+ || return;
+
+ # Look for the /x modifier near the end
+ return $elem =~ m{\b [gimso]* x [gimso]* $}mx;
+}
+
1;
__END__
=head1 CONFIGURATION
-Tabs in a leading position are allowed, but if you want to forbid all tabs
-everywhere, put this to your F<.perlcriticrc> file:
+Hard tabs in a string are always forbidden (use "\t" instead). But
+hard tabs in a leading position are allowed when they are used to indent
+code statements, C<qw()> word lists, and regular expressions with the C</x>
+modifier. However, if you want to forbid all tabs everywhere, then add
+this to your F<.perlcriticrc> file:
[CodeLayout::ProhibitHardTabs]
allow_leading_tabs = 0
# common P::C testing tools
use Perl::Critic::TestUtils qw(pcritique fcritique);
-use Test::More tests => 7;
+use Test::More tests => 10;
#-----------------------------------------------------------------------------
END_PERL
-is( pcritique($policy, \$code, \%config), 0, 'Tabs in qw()' );
+is( pcritique($policy, \$code, \%config), 0, 'Leading tabs in qw()' );
+
+#-----------------------------------------------------------------------------
+
+$code = <<"END_PERL";
+#This will be interpolated!
+
+my \@list = qw(
+\tfoo\tbar
+\tbaz\tnuts
+);
+
+END_PERL
+
+is( pcritique($policy, \$code, \%config), 1, 'Non-leading tabs in qw()' );
#-----------------------------------------------------------------------------
# RT #32440
\t(really | long)
\tpattern
/mx;
+
+#This will be interpolated!
+\$z = qr/
+\tsome
+\t(really | long)
+\tpattern
+/mx;
+
+END_PERL
+
+is( pcritique($policy, \$code, \%config), 0, 'Leading tabs in extended regex' );
+
+#-----------------------------------------------------------------------------
+# RT #32440
+
+$code = <<"END_PERL";
+#This will be interpolated!
+#Note that these regex does not have /x, so tabs are significant
+
+\$x =~ m/
+\tsome
+\tugly
+\tpattern
+/m;
+
+
+\$z = qr/
+\tsome
+\tugly
+\tpattern
+/gis;
+
+END_PERL
+
+is( pcritique($policy, \$code, \%config), 2, 'Leading tabs in non-extended regex' );
+
+#-----------------------------------------------------------------------------
+# RT #32440
+
+$code = <<"END_PERL";
+#This will be interpolated!
+#Note that these regex does not have /x, so tabs are significant
+
+\$x =~ m/
+\tsome\tugly\tpattern
+/xm;
+
END_PERL
-is( pcritique($policy, \$code, \%config), 0, 'Tabs in regex' );
+is( pcritique($policy, \$code, \%config), 1, 'Non-leading tabs in extended regex' );
#-----------------------------------------------------------------------------