File Coverage

blib/lib/Perl/Critic/PolicyFactory.pm
Criterion Covered Total %
statement 145 157 92.3
branch 31 42 73.8
condition 21 31 67.7
subroutine 30 30 100.0
pod 4 4 100.0
total 231 264 87.5


line stmt bran cond sub pod time code
1             package Perl::Critic::PolicyFactory;
2              
3 40     40   424032 use 5.010001;
  40         198  
4 40     40   244 use strict;
  40         101  
  40         796  
5 40     40   197 use warnings;
  40         90  
  40         1151  
6              
7 40     40   2169 use English qw(-no_match_vars);
  40         15297  
  40         307  
8              
9 40     40   14677 use File::Spec::Unix qw();
  40         91  
  40         851  
10 40     40   4224 use List::SomeUtils qw(any);
  40         94780  
  40         2560  
11              
12 40         1784 use Perl::Critic::Utils qw{
13             :characters
14             $POLICY_NAMESPACE
15             :data_conversion
16             policy_long_name
17             policy_short_name
18             :internal_lookup
19 40     40   5195 };
  40         115  
20 40     40   30496 use Perl::Critic::PolicyConfig;
  40         105  
  40         1333  
21 40     40   246 use Perl::Critic::Exception::AggregateConfiguration;
  40         85  
  40         1432  
22 40     40   232 use Perl::Critic::Exception::Configuration;
  40         88  
  40         1505  
23 40     40   297 use Perl::Critic::Exception::Fatal::Generic qw{ throw_generic };
  40         107  
  40         1799  
24 40     40   269 use Perl::Critic::Exception::Fatal::Internal qw{ throw_internal };
  40         109  
  40         1572  
25             use Perl::Critic::Exception::Fatal::PolicyDefinition
26 40     40   15930 qw{ throw_policy_definition };
  40         102  
  40         954  
27 40     40   18627 use Perl::Critic::Exception::Configuration::NonExistentPolicy qw< >;
  40         130  
  40         1088  
28 40     40   252 use Perl::Critic::Utils::Constants qw{ :profile_strictness };
  40         86  
  40         4670  
29              
30 40     40   258 use Exception::Class; # this must come after "use P::C::Exception::*"
  40         103  
  40         183  
31              
32             our $VERSION = '1.148';
33              
34             #-----------------------------------------------------------------------------
35              
36             # Globals. Ick!
37             my @site_policy_names = ();
38              
39             #-----------------------------------------------------------------------------
40              
41             # Blech!!! This is ug-lee. Belongs in the constructor. And it shouldn't be
42             # called "test" mode.
43             sub import {
44              
45 134     134   2091 my ( $class, %args ) = @_;
46 134         379 my $test_mode = $args{-test};
47 134         349 my $extra_test_policies = $args{'-extra-test-policies'};
48              
49 134 100       639 if ( not @site_policy_names ) {
50 40         98 my $eval_worked = eval {
51 40         21030 require Module::Pluggable;
52 40         339218 Module::Pluggable->import(search_path => $POLICY_NAMESPACE,
53             require => 1, inner => 0);
54 40         2833 @site_policy_names = plugins(); #Exported by Module::Pluggable
55 40         1620592 1;
56             };
57              
58 40 50       251 if (not $eval_worked) {
59 0 0       0 if ( $EVAL_ERROR ) {
60 0         0 throw_generic
61             qq<Can't load Policies from namespace "$POLICY_NAMESPACE": $EVAL_ERROR>;
62             }
63              
64             throw_generic
65 0         0 qq<Can't load Policies from namespace "$POLICY_NAMESPACE" for an unknown reason.>;
66             }
67              
68 40 50       209 if ( not @site_policy_names ) {
69 0         0 throw_generic
70             qq<No Policies found in namespace "$POLICY_NAMESPACE".>;
71             }
72             }
73              
74             # In test mode, only load native policies, not third-party ones. So this
75             # filters out any policy that was loaded from within a directory called
76             # "blib". During the usual "./Build test" process this works fine,
77             # but it doesn't work if you are using prove to test against the code
78             # directly in the lib/ directory.
79              
80 134 100 66 51   1135 if ( $test_mode && any {m/\b blib \b/xms} @INC ) {
  51         682  
81 51         516 @site_policy_names = _modules_from_blib( @site_policy_names );
82              
83 51 50       459 if ($extra_test_policies) {
84             my @extra_policy_full_names =
85 0         0 map { "${POLICY_NAMESPACE}::$_" } @{$extra_test_policies};
  0         0  
  0         0  
86              
87 0         0 push @site_policy_names, @extra_policy_full_names;
88             }
89             }
90              
91 134         11096 return 1;
92             }
93              
94             #-----------------------------------------------------------------------------
95             # Some static helper subs
96              
97             sub _modules_from_blib {
98 51     51   2157 my (@modules) = @_;
99 51         262 return grep { _was_loaded_from_blib( _module2path($_) ) } @modules;
  7395         13432  
100             }
101              
102             sub _module2path {
103 7395   50 7395   13349 my $module = shift || return;
104 7395         38516 return File::Spec::Unix->catdir(split m/::/xms, $module) . '.pm';
105             }
106              
107             sub _was_loaded_from_blib {
108 7395   50 7395   15354 my $path = shift || return;
109 7395         21541 my $full_path = $INC{$path};
110 7395   33     35466 return $full_path && $full_path =~ m/ (?: \A | \b b ) lib \b /xms;
111             }
112              
113             #-----------------------------------------------------------------------------
114              
115             sub new {
116              
117 3076     3076 1 13340 my ( $class, %args ) = @_;
118 3076         7510 my $self = bless {}, $class;
119 3076         12165 $self->_init( %args );
120 3076         11186 return $self;
121             }
122              
123             #-----------------------------------------------------------------------------
124              
125             sub _init {
126              
127 3076     3076   10096 my ($self, %args) = @_;
128              
129 3076         5949 my $profile = $args{-profile};
130 3076 50       9821 $self->{_profile} = $profile
131             or throw_internal q{The -profile argument is required};
132              
133 3076         6062 my $incoming_errors = $args{-errors};
134 3076         5465 my $profile_strictness = $args{'-profile-strictness'};
135 3076   66     6836 $profile_strictness ||= $PROFILE_STRICTNESS_DEFAULT;
136 3076         7002 $self->{_profile_strictness} = $profile_strictness;
137              
138 3076 50       8541 if ( $profile_strictness ne $PROFILE_STRICTNESS_QUIET ) {
139 3076         4847 my $errors;
140              
141             # If we're supposed to be strict or problems have already been found...
142 3076 100 100     17931 if (
      100        
143             $profile_strictness eq $PROFILE_STRICTNESS_FATAL
144 2920         86832 or ( $incoming_errors and @{ $incoming_errors->exceptions() } )
145             ) {
146 147 100       590 $errors =
147             $incoming_errors
148             ? $incoming_errors
149             : Perl::Critic::Exception::AggregateConfiguration->new();
150             }
151              
152 3076         122172 $self->_validate_policies_in_profile( $errors );
153              
154 3076 50 100     12985 if (
      66        
155             not $incoming_errors
156             and $errors
157             and $errors->has_exceptions()
158             ) {
159 0         0 $errors->rethrow();
160             }
161             }
162              
163 3076         22800 return $self;
164             }
165              
166             #-----------------------------------------------------------------------------
167              
168             sub create_policy {
169              
170 15273     15273 1 54754 my ($self, %args ) = @_;
171              
172             my $policy_name = $args{-name}
173 15273 100       44870 or throw_internal q{The -name argument is required};
174              
175             # Normalize policy name to a fully-qualified package name
176 15272         44331 $policy_name = policy_long_name( $policy_name );
177 15272         40686 my $policy_short_name = policy_short_name( $policy_name );
178              
179              
180             # Get the policy parameters from the user profile if they were
181             # not given to us directly. If none exist, use an empty hash.
182 15272         38855 my $profile = $self->_profile();
183 15272         24203 my $policy_config;
184 15272 100       33506 if ( $args{-params} ) {
185             $policy_config =
186             Perl::Critic::PolicyConfig->new(
187             $policy_short_name, $args{-params}
188 2910         13162 );
189             }
190             else {
191 12362         38882 $policy_config = $profile->policy_params($policy_name);
192 12362   33     35259 $policy_config ||=
193             Perl::Critic::PolicyConfig->new( $policy_short_name );
194             }
195              
196             # Pull out base parameters.
197 15272         38312 return $self->_instantiate_policy( $policy_name, $policy_config );
198             }
199              
200             #-----------------------------------------------------------------------------
201              
202             sub create_all_policies {
203              
204 82     82 1 356 my ( $self, $incoming_errors ) = @_;
205              
206 82 100       272 my $errors =
207             $incoming_errors
208             ? $incoming_errors
209             : Perl::Critic::Exception::AggregateConfiguration->new();
210 82         1205 my @policies;
211              
212 82         267 foreach my $name ( site_policy_names() ) {
213 11890         21749 my $policy = eval { $self->create_policy( -name => $name ) };
  11890         36896  
214              
215 11890         43323 $errors->add_exception_or_rethrow( $EVAL_ERROR );
216              
217 11890 100       45077 if ( $policy ) {
218 11889         322477 push @policies, $policy;
219             }
220             }
221              
222 82 50 66     3239 if ( not $incoming_errors and $errors->has_exceptions() ) {
223 0         0 $errors->rethrow();
224             }
225              
226 82         3302 return @policies;
227             }
228              
229             #-----------------------------------------------------------------------------
230              
231             sub site_policy_names {
232 3216     3216 1 101292 my @sorted_policy_names = sort @site_policy_names;
233 3216         65601 return @sorted_policy_names;
234             }
235              
236             #-----------------------------------------------------------------------------
237              
238             sub _profile {
239 18348     18348   33389 my ($self) = @_;
240              
241 18348         40700 return $self->{_profile};
242             }
243              
244             #-----------------------------------------------------------------------------
245              
246             # This two-phase initialization is caused by the historical lack of a
247             # requirement for Policies to invoke their super-constructor.
248             sub _instantiate_policy {
249 15272     15272   30796 my ($self, $policy_name, $policy_config) = @_;
250              
251 15272         51557 $policy_config->set_profile_strictness( $self->{_profile_strictness} );
252              
253 15272         24792 my $policy = eval { $policy_name->new( %{$policy_config} ) };
  15272         24945  
  15272         138718  
254 15272         55320 _handle_policy_instantiation_exception(
255             $policy_name,
256             $policy, # Note: being used as a boolean here.
257             $EVAL_ERROR,
258             );
259              
260 15122         53227 $policy->__set_config( $policy_config );
261              
262 15122         25843 my $eval_worked = eval { $policy->__set_base_parameters(); 1; };
  15122         63737  
  15121         32659  
263 15122         44988 _handle_policy_instantiation_exception(
264             $policy_name, $eval_worked, $EVAL_ERROR,
265             );
266              
267 15121         49836 return $policy;
268             }
269              
270             sub _handle_policy_instantiation_exception {
271 30394     30394   72553 my ($policy_name, $eval_worked, $eval_error) = @_;
272              
273 30394 100       102077 if (not $eval_worked) {
274 151 50       484 if ($eval_error) {
275 151         1157 my $exception = Exception::Class->caught();
276              
277 151 100       1009 if (ref $exception) {
278 149         369 $exception->rethrow();
279             }
280              
281             throw_policy_definition
282 2         14 qq<Unable to create policy "$policy_name": $eval_error>;
283             }
284              
285             throw_policy_definition
286 0         0 qq<Unable to create policy "$policy_name" for an unknown reason.>;
287             }
288              
289 30243         427076 return;
290             }
291              
292             #-----------------------------------------------------------------------------
293              
294             sub _validate_policies_in_profile {
295 3076     3076   8032 my ($self, $errors) = @_;
296              
297 3076         8358 my $profile = $self->_profile();
298 3076         10857 my %known_policies = hashify( $self->site_policy_names() );
299              
300 3076         44505 for my $policy_name ( $profile->listed_policies() ) {
301 1833 100       3406 if ( not exists $known_policies{$policy_name} ) {
302 2         8 my $message = qq{Policy "$policy_name" is not installed.};
303              
304 2 50       8 if ( $errors ) {
305 0         0 $errors->add_exception(
306             Perl::Critic::Exception::Configuration::NonExistentPolicy->new(
307             policy => $policy_name,
308             )
309             );
310             }
311             else {
312 2         21 warn qq{$message\n};
313             }
314             }
315             }
316              
317 3076         31692 return;
318             }
319              
320             #-----------------------------------------------------------------------------
321              
322             1;
323              
324             __END__
325              
326              
327             =pod
328              
329             =for stopwords PolicyFactory -params
330              
331             =head1 NAME
332              
333             Perl::Critic::PolicyFactory - Instantiates Policy objects.
334              
335              
336             =head1 DESCRIPTION
337              
338             This is a helper class that instantiates
339             L<Perl::Critic::Policy|Perl::Critic::Policy> objects with the user's
340             preferred parameters. There are no user-serviceable parts here.
341              
342              
343             =head1 INTERFACE SUPPORT
344              
345             This is considered to be a non-public class. Its interface is subject
346             to change without notice.
347              
348              
349             =head1 CONSTRUCTOR
350              
351             =over
352              
353             =item C<< new( -profile => $profile, -errors => $config_errors ) >>
354              
355             Returns a reference to a new Perl::Critic::PolicyFactory object.
356              
357             B<-profile> is a reference to a
358             L<Perl::Critic::UserProfile|Perl::Critic::UserProfile> object. This
359             argument is required.
360              
361             B<-errors> is a reference to an instance of
362             L<Perl::Critic::ConfigErrors|Perl::Critic::ConfigErrors>. This
363             argument is optional. If specified, than any problems found will be
364             added to the object.
365              
366              
367             =back
368              
369              
370             =head1 METHODS
371              
372             =over
373              
374             =item C<< create_policy( -name => $policy_name, -params => \%param_hash ) >>
375              
376             Creates one Policy object. If the object cannot be instantiated, it
377             will throw a fatal exception. Otherwise, it returns a reference to
378             the new Policy object.
379              
380             B<-name> is the name of a L<Perl::Critic::Policy|Perl::Critic::Policy>
381             subclass module. The C<'Perl::Critic::Policy'> portion of the name
382             can be omitted for brevity. This argument is required.
383              
384             B<-params> is an optional reference to hash of parameters that will be
385             passed into the constructor of the Policy. If C<-params> is not
386             defined, we will use the appropriate Policy parameters from the
387             L<Perl::Critic::UserProfile|Perl::Critic::UserProfile>.
388              
389             Note that the Policy will not have had
390             L<Perl::Critic::Policy/"initialize_if_enabled"> invoked on it, so it
391             may not yet be usable.
392              
393              
394             =item C< create_all_policies() >
395              
396             Constructs and returns one instance of each
397             L<Perl::Critic::Policy|Perl::Critic::Policy> subclass that is
398             installed on the local system. Each Policy will be created with the
399             appropriate parameters from the user's configuration profile.
400              
401             Note that the Policies will not have had
402             L<Perl::Critic::Policy/"initialize_if_enabled"> invoked on them, so
403             they may not yet be usable.
404              
405              
406             =back
407              
408              
409             =head1 SUBROUTINES
410              
411             Perl::Critic::PolicyFactory has a few static subroutines that are used
412             internally, but may be useful to you in some way.
413              
414             =over
415              
416             =item C<site_policy_names()>
417              
418             Returns a list of all the Policy modules that are currently installed
419             in the Perl::Critic:Policy namespace. These will include modules that
420             are distributed with Perl::Critic plus any third-party modules that
421             have been installed.
422              
423              
424             =back
425              
426              
427             =head1 AUTHOR
428              
429             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
430              
431              
432             =head1 COPYRIGHT
433              
434             Copyright (c) 2005-2011 Imaginative Software Systems
435              
436             This program is free software; you can redistribute it and/or modify
437             it under the same terms as Perl itself. The full text of this license
438             can be found in the LICENSE file included with this module.
439              
440             =cut
441              
442             # Local Variables:
443             # mode: cperl
444             # cperl-indent-level: 4
445             # fill-column: 78
446             # indent-tabs-mode: nil
447             # c-indentation-style: bsd
448             # End:
449             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :