File Coverage

blib/lib/Perl/Critic/Policy/Moose/RequireMakeImmutable.pm
Criterion Covered Total %
statement 60 62 96.7
branch 25 40 62.5
condition n/a
subroutine 14 15 93.3
pod 5 6 83.3
total 104 123 84.5


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Moose::RequireMakeImmutable;
2              
3 1     1   491 use strict;
  1         1  
  1         23  
4 1     1   3 use warnings;
  1         1  
  1         43  
5 1     1   4 use namespace::autoclean;
  1         1  
  1         4  
6              
7             our $VERSION = '1.05';
8              
9 1     1   48 use Readonly ();
  1         1  
  1         12  
10              
11 1     1   3 use Perl::Critic::Utils qw< :booleans :severities >;
  1         1  
  1         42  
12 1     1   109 use Perl::Critic::Utils::PPI qw< is_ppi_generic_statement >;
  1         2  
  1         33  
13              
14 1     1   3 use base 'Perl::Critic::Policy';
  1         12  
  1         420  
15              
16             Readonly::Scalar my $DESCRIPTION => 'No call was made to make_immutable().';
17             Readonly::Scalar my $EXPLANATION =>
18             q<Moose can't optimize itself if classes remain mutable.>;
19              
20             sub supported_parameters {
21             return (
22             {
23 4     4 0 10140 name => 'equivalent_modules',
24             description =>
25             q<The additional modules to treat as equivalent to "Moose".>,
26             default_string => 'Moose',
27             behavior => 'string list',
28             list_always_present_values => [qw< Moose >],
29             },
30             );
31             }
32              
33 2     2 1 29 sub default_severity { return $SEVERITY_MEDIUM; }
34 0     0 1 0 sub default_themes { return qw( moose performance ); }
35 4     4 1 223 sub applies_to { return 'PPI::Document' }
36              
37             sub prepare_to_scan_document {
38 4     4 1 27054 my ( $self, $document ) = @_;
39              
40 4         11 return $self->_is_interesting_document($document);
41             }
42              
43             sub _is_interesting_document {
44 4     4   7 my ( $self, $document ) = @_;
45              
46 4         6 foreach my $module ( keys %{ $self->{_equivalent_modules} } ) {
  4         17  
47 5 100       85 return $TRUE if $document->uses_module($module);
48             }
49              
50 0         0 return $FALSE;
51             }
52              
53             sub violates {
54 4     4 1 31 my ( $self, undef, $document ) = @_;
55              
56             my $makes_immutable = $document->find_any(
57             sub {
58 155     155   1993 my ( undef, $element ) = @_;
59              
60 155 100       271 return $FALSE if not is_ppi_generic_statement($element);
61              
62 6         43 my $current_token = $element->schild(0);
63 6 50       64 return $FALSE if not $current_token;
64 6 50       18 return $FALSE if not $current_token->isa('PPI::Token::Word');
65 6 100       14 return $FALSE if $current_token->content() ne '__PACKAGE__';
66              
67 2         11 $current_token = $current_token->snext_sibling();
68 2 50       38 return $FALSE if not $current_token;
69 2 50       7 return $FALSE if not $current_token->isa('PPI::Token::Operator');
70 2 50       5 return $FALSE if $current_token->content() ne '->';
71              
72 2         12 $current_token = $current_token->snext_sibling();
73 2 50       23 return $FALSE if not $current_token;
74 2 50       7 return $FALSE if not $current_token->isa('PPI::Token::Word');
75 2 50       4 return $FALSE if $current_token->content() ne 'meta';
76              
77 2         11 $current_token = $current_token->snext_sibling();
78 2 50       29 return $FALSE if not $current_token;
79 2 100       6 if ( $current_token->isa('PPI::Structure::List') ) {
80 1         8 $current_token = $current_token->snext_sibling();
81 1 50       13 return $FALSE if not $current_token;
82             }
83              
84 2 50       7 return $FALSE if not $current_token->isa('PPI::Token::Operator');
85 2 50       6 return $FALSE if $current_token->content() ne '->';
86              
87 2         10 $current_token = $current_token->snext_sibling();
88 2 50       22 return $FALSE if not $current_token;
89 2 50       8 return $FALSE if not $current_token->isa('PPI::Token::Word');
90 2 50       5 return $FALSE if $current_token->content() ne 'make_immutable';
91              
92 2         8 return $TRUE;
93             }
94 4         31 );
95              
96 4 100       102 return if $makes_immutable;
97 2         17 return $self->violation( $DESCRIPTION, $EXPLANATION, $document );
98             }
99              
100             1;
101              
102             # ABSTRACT: Ensure that you've made your Moose code fast
103              
104             __END__
105              
106             =pod
107              
108             =encoding UTF-8
109              
110             =head1 NAME
111              
112             Perl::Critic::Policy::Moose::RequireMakeImmutable - Ensure that you've made your Moose code fast
113              
114             =head1 VERSION
115              
116             version 1.05
117              
118             =head1 DESCRIPTION
119              
120             L<Moose> is very flexible. That flexibility comes at a performance cost. You
121             can ameliorate some of that cost by telling Moose when you are done putting
122             your classes together.
123              
124             Thus, if you C<use Moose>, this policy requires that you do
125             C<< __PACKAGE__->meta()->make_immutable() >>.
126              
127             =head1 AFFILIATION
128              
129             This policy is part of L<Perl::Critic::Moose>.
130              
131             =head1 CONFIGURATION
132              
133             There is a single option, C<equivalent_modules>. This allows you to specify
134             modules that should be treated the same as L<Moose> and L<Moose::Role>, if,
135             say, you were doing something with L<Moose::Exporter>. For example, if you
136             were to have this in your F<.perlcriticrc> file:
137              
138             [Moose::RequireMakeImmutable]
139             equivalent_modules = MyCompany::Moose MooseX::NewThing
140              
141             then the following code would result in a violation:
142              
143             package Baz;
144              
145             use MyCompany::Moose;
146              
147             sub new {
148             ...
149             }
150              
151             # no make_immutable call
152              
153             =head1 SUPPORT
154              
155             Bugs may be submitted through L<the RT bug tracker|http://rt.cpan.org/Public/Dist/Display.html?Name=Perl-Critic-Moose>
156             (or L<bug-perl-critic-moose@rt.cpan.org|mailto:bug-perl-critic-moose@rt.cpan.org>).
157              
158             I am also usually active on IRC as 'drolsky' on C<irc://irc.perl.org>.
159              
160             =head1 AUTHORS
161              
162             =over 4
163              
164             =item *
165              
166             Elliot Shank <perl@galumph.com>
167              
168             =item *
169              
170             Dave Rolsky <autarch@urth.org>
171              
172             =back
173              
174             =head1 COPYRIGHT AND LICENSE
175              
176             This software is copyright (c) 2008 - 2016 by Elliot Shank.
177              
178             This is free software; you can redistribute it and/or modify it under
179             the same terms as the Perl 5 programming language system itself.
180              
181             =cut