File Coverage

blib/lib/Perl/Critic/Policy/References/ProhibitComplexDoubleSigils.pm
Criterion Covered Total %
statement 34 35 97.1
branch 13 16 81.2
condition 3 3 100.0
subroutine 10 11 90.9
pod 4 5 80.0
total 64 70 91.4


line stmt bran cond sub pod time code
1             #
2             # Copyright (C) 2015 Tomasz Konojacki
3             #
4             # This library is free software; you can redistribute it and/or modify
5             # it under the same terms as Perl itself, either Perl version 5.20.1 or,
6             # at your option, any later version of Perl 5 you may have available.
7             #
8              
9             package Perl::Critic::Policy::References::ProhibitComplexDoubleSigils;
10              
11 2     2   174347 use strict;
  2         3  
  2         66  
12 2     2   9 use warnings;
  2         3  
  2         41  
13              
14 2     2   430 use Readonly;
  2         2300  
  2         93  
15 2     2   8 use List::Util;
  2         2  
  2         93  
16              
17 2     2   560 use Perl::Critic::Utils qw{ :severities };
  2         90177  
  2         85  
18 2     2   602 use base 'Perl::Critic::Policy';
  2         4  
  2         1124  
19              
20             our $VERSION = '0.2';
21              
22             #-----------------------------------------------------------------------------
23              
24             Readonly::Scalar my $DESC => q{Complex double-sigil dereferences};
25             Readonly::Scalar my $EXPL => q{Found complex double-sigil dereference without curly braces.};
26              
27             #-----------------------------------------------------------------------------
28              
29 18     18 0 55614 sub supported_parameters { return () }
30 4     4 1 45 sub default_severity { return $SEVERITY_LOW }
31 0     0 1 0 sub default_themes { return qw(cosmetic) }
32 18     18 1 79865 sub applies_to { return 'PPI::Token::Cast' }
33              
34             #-----------------------------------------------------------------------------
35              
36             sub violates {
37 20     20 1 354 my ($self, $elem) = @_;
38              
39 20 50       63 return if $elem eq q{\\};
40              
41 20         370 my $sib = $elem->snext_sibling;
42              
43 20 50       447 return if !$sib;
44 20 100       156 return if $sib->isa('PPI::Structure::Block');
45              
46 10 50       31 if ($sib->isa('PPI::Token::Symbol')) {
47 10         26 my $next_sib = $sib->snext_sibling;
48 10 100       145 return if !$next_sib;
49              
50             # e.g $$fobar[0]->{a} or $$foo{key}->[6]
51 8 100 100     69 if ($next_sib->isa('PPI::Structure::Subscript')) {
    100          
    100          
52 2         15 return $self->violation( $DESC, $EXPL, $elem );
53             }
54             # e.g. &$foobar(1, 2, 3)
55             elsif ($next_sib->isa('PPI::Structure::List')) {
56 1         15 return $self->violation( $DESC, $EXPL, $elem );
57             }
58             # e.g. @$foobar->{foo}->[0]
59             elsif ($next_sib->isa('PPI::Token::Operator') && $next_sib eq q/->/) {
60 1         17 return $self->violation( $DESC, $EXPL, $elem );
61             }
62             }
63              
64 4         54 return; #ok!
65             }
66              
67             'Bei Mir Bistu Shein';
68              
69             __END__
70              
71             =head1 NAME
72              
73             Perl::Critic::Policy::References::ProhibitComplexDoubleSigils - allow C<$$foo>
74             but not C<$$foo[1]-E<gt>{dadsdas}-E<gt>[7]>.
75              
76             =head1 DESCRIPTION
77              
78             This L<Perl::Critic> policy is very similar to
79             L<Perl::Critic::Policy::References::ProhibitDoubleSigils> but it allows
80             non-complex double sigil dereferences, for details see EXAMPLES and RATIONALE
81             sections.
82              
83             =head1 EXAMPLES
84              
85             # These are allowed:
86             my @array = @$arrayref;
87             my %hash = %$hashref;
88             my $scalar = $$scalarref;
89              
90             for (@$arrayref) {
91             ...
92             }
93              
94             # These are not:
95             my $scalar = $$arrayref[0]->{foobar}; # use these instead:
96             # $arrayref->[0]->{foobar}
97             # ${$arrayref}[0]->{foobar}
98              
99             my $scalar = $$hashref{bar}->[1]; # use these instead:
100             # $hashref->{bar}->[1]
101             # ${$hashref}{bar}->[1]
102              
103             &$coderef()->{1234}->[1]; # use these instead:
104             # $coderef->()->{1234}->[1]
105             # &{$coderef}()->{1234}->[1]
106              
107             ...
108              
109             =head1 RATIONALE
110              
111             There are some cases when using braces in dereferences makes sense, I don't
112             deny it, but in my opinion it reduces code readability in most common cases.
113             L<Perl::Critic::Policy::References::ProhibitDoubleSigils> is simply too
114             strict. Consider following examples:
115              
116             # exhibit A:
117             for (@{$foo}) {
118             ...
119             }
120              
121             # exhibit B:
122             for (@$foo) {
123             ...
124             }
125              
126             If you think that C<B> is more legible, this critic policy is for you.
127              
128             =head1 CAVEATS
129              
130             Enabling both L<Perl::Critic::Policy::References::ProhibitDoubleSigils> and
131             this policy is not a very wise choice.
132              
133             =head1 EXPORT
134              
135             None by default.
136              
137             =head1 FOSSIL REPOSTIORY
138              
139             Perl::Critic::policy::References::ProhibitComplexDoubleSigils Fossil repository
140             is hosted at xenu.tk:
141              
142             http://code.xenu.tk/repos.cgi/prohibit-complex-double-sigils
143              
144             =head1 SEE ALSO
145              
146             =over 4
147              
148             =item *
149             L<Perl::Critic>
150              
151             =item *
152             L<Perl::Critic::Policy::References::ProhibitDoubleSigils>
153              
154             =back
155              
156             =head1 AUTHOR
157              
158             Tomasz Konojacki <me@xenu.tk>, http://xenu.tk
159              
160             =head1 COPYRIGHT AND LICENSE
161              
162             Copyright (C) 2015 Tomasz Konojacki
163              
164             This library is free software; you can redistribute it and/or modify
165             it under the same terms as Perl itself, either Perl version 5.20.1 or,
166             at your option, any later version of Perl 5 you may have available.
167              
168             =cut