File Coverage

blib/lib/Perl/Critic/Policy/Community/Prototypes.pm
Criterion Covered Total %
statement 40 41 97.5
branch 14 16 87.5
condition 17 22 77.2
subroutine 11 12 91.6
pod 4 5 80.0
total 86 96 89.5


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Community::Prototypes;
2              
3 1     1   988 use strict;
  1         3  
  1         44  
4 1     1   7 use warnings;
  1         2  
  1         61  
5              
6 1     1   7 use Perl::Critic::Utils qw(:severities :classification :ppi);
  1         2  
  1         71  
7 1     1   483 use parent 'Perl::Critic::Policy';
  1         3  
  1         6  
8 1     1   79 use version;
  1         2  
  1         42  
9              
10             our $VERSION = 'v1.0.4';
11              
12 1     1   203 use constant DESC => 'Using function prototypes';
  1         3  
  1         104  
13 1     1   8 use constant EXPL => 'Function prototypes (sub foo ($@) { ... }) will usually not do what you want. Omit the prototype, or use signatures instead.';
  1         1  
  1         666  
14              
15             sub supported_parameters {
16             (
17             {
18 10     10 0 62846 name => 'signature_enablers',
19             description => 'Non-standard modules to recognize as enabling signatures',
20             behavior => 'string list',
21             },
22             )
23             }
24              
25 1     1 1 20 sub default_severity { $SEVERITY_MEDIUM }
26 0     0 1 0 sub default_themes { 'community' }
27 10     10 1 127395 sub applies_to { 'PPI::Document' }
28              
29             sub violates {
30 10     10 1 174 my ($self, $elem) = @_;
31              
32             # Check if signatures are enabled
33 10   100     46 my $includes = $elem->find('PPI::Statement::Include') || [];
34 10         217 foreach my $include (@$includes) {
35 6 50       31 next unless $include->type eq 'use';
36 6 100 66     214 return () if $include->version and version->parse($include->version) >= version->parse('v5.36');
37 5 100 66     163 return () if $include->pragma eq 'feature' and $include =~ m/\bsignatures\b/;
38 4 100 66     171 return () if $include->pragma eq 'experimental' and $include =~ m/\bsignatures\b/;
39 3 100 66     107 return () if $include->module eq 'Mojo::Base' and $include =~ m/-signatures\b/;
40 2 100 66     59 return () if $include->module eq 'Mojolicious::Lite' and $include =~ m/-signatures\b/;
41 1 50       31 return () if exists $self->{_signature_enablers}{$include->module};
42             }
43            
44 4   100     17 my $prototypes = $elem->find('PPI::Token::Prototype') || [];
45 4         55 my @violations;
46 4         13 foreach my $prototype (@$prototypes) {
47             # Empty prototypes and prototypes containing & can be useful
48 3 100 100     17 next if $prototype->prototype eq '' or $prototype->prototype =~ /&/;
49 1         47 push @violations, $self->violation(DESC, EXPL, $prototype);
50             }
51            
52 4         384 return @violations;
53             }
54              
55             1;
56              
57             =head1 NAME
58              
59             Perl::Critic::Policy::Community::Prototypes - Don't use function prototypes
60              
61             =head1 DESCRIPTION
62              
63             Function prototypes are primarily a hint to the Perl parser for parsing the
64             function's argument list. They are not a way to validate or count the arguments
65             passed to the function, and will cause confusion if used this way. Often, the
66             prototype can simply be left out, but see L<perlsub/"Signatures"> for a more
67             modern method of declaring arguments.
68              
69             sub foo ($$) { ... } # not ok
70             sub foo { ... } # ok
71             use feature 'signatures'; sub foo ($bar, $baz) { ... } # ok
72             use experimental 'signatures'; sub foo ($bar, $baz) { ... } # ok
73              
74             This policy is similar to the core policy
75             L<Perl::Critic::Policy::Subroutines::ProhibitSubroutinePrototypes>, but
76             additionally ignores files using the C<signatures> feature (which is also
77             enabled by a C<use> declaration of perl version 5.36 or higher), and allows
78             empty prototypes and prototypes containing C<&>, as these are often useful for
79             structural behavior.
80              
81             =head1 AFFILIATION
82              
83             This policy is part of L<Perl::Critic::Community>.
84              
85             =head1 CONFIGURATION
86              
87             This policy can be configured to recognize additional modules as enabling the
88             C<signatures> feature, by putting an entry in a C<.perlcriticrc> file like
89             this:
90              
91             [Community::Prototypes]
92             signature_enablers = MyApp::Base
93              
94             =head1 AUTHOR
95              
96             Dan Book, C<dbook@cpan.org>
97              
98             =head1 COPYRIGHT AND LICENSE
99              
100             Copyright 2015, Dan Book.
101              
102             This library is free software; you may redistribute it and/or modify it under
103             the terms of the Artistic License version 2.0.
104              
105             =head1 SEE ALSO
106              
107             L<Perl::Critic>