1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
# Copyright 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2021 Kevin Ryde
# This file is part of Perl-Critic-Pulp.
# Perl-Critic-Pulp is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3, or (at your option) any later
# version.
#
# Perl-Critic-Pulp is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.
package Perl::Critic::Policy::Miscellanea::TextDomainUnused;
use 5.006;
use strict;
use warnings;
use base 'Perl::Critic::Policy';
use Perl::Critic::Utils qw(is_function_call);
our $VERSION = 99;
use constant supported_parameters => ();
use constant default_severity => $Perl::Critic::Utils::SEVERITY_LOW;
use constant default_themes => qw(pulp cosmetic);
use constant applies_to => 'PPI::Document';
sub violates {
my ($self, $elem, $document) = @_;
my $use = _find_use_locale_textdomain($document) || return;
if (_any_calls_locale_textdomain($document)) { return; }
if (_any_vars_locale_textdomain($document)) { return; }
if (_any_strings_locale_textdomain($document)) { return; }
return $self->violation
('Locale::TextDomain imported, but none of its functions used',
'',
$use);
}
# return a PPI::Statement::Include which is a "use" or "require" of
# Locale::TextDomain, or return false if there's no such
sub _find_use_locale_textdomain {
my ($document) = @_;
my $aref = $document->find ('PPI::Statement::Include')
|| return; # if no includes at all
return List::Util::first { $_->type ne 'no'
&& ($_->module||'') eq 'Locale::TextDomain'
} @$aref;
}
# The following qw() copied from @Locale::TextDomain::EXPORT of libintl-perl
# 1.18, with $__ %__ moved to %vars below. __p and friends are new in 1.17,
# but no need to check that.
#
my %funcs = map {($_=>1)}
qw(__ __x __n __nx __xn __p __px __np __npx
N__ N__n N__p N__np);
# and also as full names "Locale::TextDomain::__"
foreach (keys %funcs) {
$funcs{"Locale::TextDomain::$_"} = 1;
}
# return true if $document has any of the Locale::TextDomain functions used,
# like __() etc
sub _any_calls_locale_textdomain {
my ($document) = @_;
my $aref = $document->find ('PPI::Token::Word')
|| return; # if no word tokens at all
return List::Util::first { $funcs{$_->content}
&& is_function_call($_)
} @$aref;
}
## no critic (RequireInterpolationOfMetachars)
my %vars = ('$__' => 1,
'%__' => 1);
## use critic
sub _any_vars_locale_textdomain {
my ($document) = @_;
my $aref = $document->find ('PPI::Token::Symbol')
|| return; # if no symbols at all
return List::Util::first { $vars{$_->symbol} } @$aref;
}
sub _any_strings_locale_textdomain {
my ($document) = @_;
my $aref = $document->find ('PPI::Token::Quote')
|| return; # if no strings at all
return List::Util::first { ($_->isa('PPI::Token::Quote::Interpolate')
|| $_->isa('PPI::Token::Quote::Double'))
&& $_->string =~ /\$__(\W|$)/ } @$aref;
}
1;
__END__
=for stopwords textdomain perlcritic TextDomainUnused eg TextDomain PPI Ryde
=head1 NAME
Perl::Critic::Policy::Miscellanea::TextDomainUnused - check for Locale::TextDomain imported but unused
=head1 DESCRIPTION
This policy is part of the L<C<Perl::Critic::Pulp>|Perl::Critic::Pulp>
add-on. It reports when you have L<C<Locale::TextDomain>|Locale::TextDomain>
like
use Locale::TextDomain ('MyMessageDomain');
but then don't use any of its functions or variables
__ __x __n __nx __xn
__p __px __np __npx
N__ N__n N__p N__np
%__ $__
C<Locale::TextDomain> is not needed when not used, but it's also not
actively harmful so this policy is only low severity and under the
C<cosmetic> theme (see L<Perl::Critic/POLICY THEMES>).
The check is good if you've got C<Locale::TextDomain> as boilerplate code in
most of your program, but in some modules it's unused. You can remove it
entirely from non-interactive modules, or comment it out from modules which
might have messages but don't yet. The best thing picked up is when your
boilerplate has got into a programmatic module which shouldn't say anything
at the user level.
The saving from removing unused C<Locale::TextDomain> is modest, just some
imports and a hash entry holding the "textdomain" for the package.
It's easy to imagine a general kind of "module imported but unused" policy
check, but in practice its hard for perlcritic to know the automatic imports
of every module, and quite a few modules have side-effects, so this
TextDomainUnused policy just starts with one case of an unused include.
=head2 Interpolated Variables
The variables C<%__> and C<$__> are recognised in double-quote interpolated
strings just by looking for a C<$__> somewhere in the string, eg.
print "*** $__{'A Message'} ***\n"; # ok
It's not hard to trick the recognition with escapes, or a hash slice style,
but in general taking any C<$__> to be a TextDomain use is close enough.
(Perhaps in the future PPI will do a full parse of interpolated
expressions.)
=head1 SEE ALSO
L<Perl::Critic::Pulp>,
L<Perl::Critic>,
L<Locale::TextDomain>,
L<Perl::Critic::Policy::Miscellanea::TextDomainPlaceholders>
=head1 HOME PAGE
L<http://user42.tuxfamily.org/perl-critic-pulp/index.html>
=head1 COPYRIGHT
Copyright 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2021 Kevin Ryde
Perl-Critic-Pulp is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
Perl-Critic-Pulp is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.
=cut
|