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   405495 use 5.010001;
  40         203  
4 40     40   253 use strict;
  40         101  
  40         906  
5 40     40   220 use warnings;
  40         90  
  40         1188  
6              
7 40     40   2195 use English qw(-no_match_vars);
  40         14791  
  40         312  
8              
9 40     40   15047 use File::Spec::Unix qw();
  40         103  
  40         889  
10 40     40   4641 use List::SomeUtils qw(any);
  40         108116  
  40         2715  
11              
12 40         1792 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   5161 };
  40         118  
20 40     40   30382 use Perl::Critic::PolicyConfig;
  40         107  
  40         1395  
21 40     40   280 use Perl::Critic::Exception::AggregateConfiguration;
  40         82  
  40         1545  
22 40     40   259 use Perl::Critic::Exception::Configuration;
  40         95  
  40         1548  
23 40     40   252 use Perl::Critic::Exception::Fatal::Generic qw{ throw_generic };
  40         85  
  40         1856  
24 40     40   259 use Perl::Critic::Exception::Fatal::Internal qw{ throw_internal };
  40         118  
  40         1528  
25             use Perl::Critic::Exception::Fatal::PolicyDefinition
26 40     40   16077 qw{ throw_policy_definition };
  40         116  
  40         988  
27 40     40   19321 use Perl::Critic::Exception::Configuration::NonExistentPolicy qw< >;
  40         125  
  40         1044  
28 40     40   261 use Perl::Critic::Utils::Constants qw{ :profile_strictness };
  40         110  
  40         4787  
29              
30 40     40   282 use Exception::Class; # this must come after "use P::C::Exception::*"
  40         106  
  40         247  
31              
32             our $VERSION = '1.146';
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   1967 my ( $class, %args ) = @_;
46 134         392 my $test_mode = $args{-test};
47 134         316 my $extra_test_policies = $args{'-extra-test-policies'};
48              
49 134 100       633 if ( not @site_policy_names ) {
50 40         84 my $eval_worked = eval {
51 40         20950 require Module::Pluggable;
52 40         339976 Module::Pluggable->import(search_path => $POLICY_NAMESPACE,
53             require => 1, inner => 0);
54 40         2990 @site_policy_names = plugins(); #Exported by Module::Pluggable
55 40         1632595 1;
56             };
57              
58 40 50       255 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       202 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   1126 if ( $test_mode && any {m/\b blib \b/xms} @INC ) {
  51         693  
81 51         492 @site_policy_names = _modules_from_blib( @site_policy_names );
82              
83 51 50       425 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         11191 return 1;
92             }
93              
94             #-----------------------------------------------------------------------------
95             # Some static helper subs
96              
97             sub _modules_from_blib {
98 51     51   2246 my (@modules) = @_;
99 51         283 return grep { _was_loaded_from_blib( _module2path($_) ) } @modules;
  7395         13195  
100             }
101              
102             sub _module2path {
103 7395   50 7395   13544 my $module = shift || return;
104 7395         38202 return File::Spec::Unix->catdir(split m/::/xms, $module) . '.pm';
105             }
106              
107             sub _was_loaded_from_blib {
108 7395   50 7395   15306 my $path = shift || return;
109 7395         20702 my $full_path = $INC{$path};
110 7395   33     34845 return $full_path && $full_path =~ m/ (?: \A | \b b ) lib \b /xms;
111             }
112              
113             #-----------------------------------------------------------------------------
114              
115             sub new {
116              
117 3076     3076 1 13907 my ( $class, %args ) = @_;
118 3076         7387 my $self = bless {}, $class;
119 3076         13221 $self->_init( %args );
120 3076         11477 return $self;
121             }
122              
123             #-----------------------------------------------------------------------------
124              
125             sub _init {
126              
127 3076     3076   10170 my ($self, %args) = @_;
128              
129 3076         6105 my $profile = $args{-profile};
130 3076 50       10681 $self->{_profile} = $profile
131             or throw_internal q{The -profile argument is required};
132              
133 3076         6666 my $incoming_errors = $args{-errors};
134 3076         5597 my $profile_strictness = $args{'-profile-strictness'};
135 3076   66     7188 $profile_strictness ||= $PROFILE_STRICTNESS_DEFAULT;
136 3076         6133 $self->{_profile_strictness} = $profile_strictness;
137              
138 3076 50       8670 if ( $profile_strictness ne $PROFILE_STRICTNESS_QUIET ) {
139 3076         4708 my $errors;
140              
141             # If we're supposed to be strict or problems have already been found...
142 3076 100 100     17123 if (
      100        
143             $profile_strictness eq $PROFILE_STRICTNESS_FATAL
144 2920         88823 or ( $incoming_errors and @{ $incoming_errors->exceptions() } )
145             ) {
146 147 100       626 $errors =
147             $incoming_errors
148             ? $incoming_errors
149             : Perl::Critic::Exception::AggregateConfiguration->new();
150             }
151              
152 3076         121897 $self->_validate_policies_in_profile( $errors );
153              
154 3076 50 100     13044 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         24626 return $self;
164             }
165              
166             #-----------------------------------------------------------------------------
167              
168             sub create_policy {
169              
170 15273     15273 1 56080 my ($self, %args ) = @_;
171              
172             my $policy_name = $args{-name}
173 15273 100       46263 or throw_internal q{The -name argument is required};
174              
175             # Normalize policy name to a fully-qualified package name
176 15272         43869 $policy_name = policy_long_name( $policy_name );
177 15272         37759 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         38270 my $profile = $self->_profile();
183 15272         24826 my $policy_config;
184 15272 100       35221 if ( $args{-params} ) {
185             $policy_config =
186             Perl::Critic::PolicyConfig->new(
187             $policy_short_name, $args{-params}
188 2910         13635 );
189             }
190             else {
191 12362         40246 $policy_config = $profile->policy_params($policy_name);
192 12362   33     39802 $policy_config ||=
193             Perl::Critic::PolicyConfig->new( $policy_short_name );
194             }
195              
196             # Pull out base parameters.
197 15272         37853 return $self->_instantiate_policy( $policy_name, $policy_config );
198             }
199              
200             #-----------------------------------------------------------------------------
201              
202             sub create_all_policies {
203              
204 82     82 1 285 my ( $self, $incoming_errors ) = @_;
205              
206 82 100       280 my $errors =
207             $incoming_errors
208             ? $incoming_errors
209             : Perl::Critic::Exception::AggregateConfiguration->new();
210 82         1242 my @policies;
211              
212 82         281 foreach my $name ( site_policy_names() ) {
213 11890         21824 my $policy = eval { $self->create_policy( -name => $name ) };
  11890         39053  
214              
215 11890         46478 $errors->add_exception_or_rethrow( $EVAL_ERROR );
216              
217 11890 100       46578 if ( $policy ) {
218 11889         324707 push @policies, $policy;
219             }
220             }
221              
222 82 50 66     3607 if ( not $incoming_errors and $errors->has_exceptions() ) {
223 0         0 $errors->rethrow();
224             }
225              
226 82         2960 return @policies;
227             }
228              
229             #-----------------------------------------------------------------------------
230              
231             sub site_policy_names {
232 3216     3216 1 108276 my @sorted_policy_names = sort @site_policy_names;
233 3216         67116 return @sorted_policy_names;
234             }
235              
236             #-----------------------------------------------------------------------------
237              
238             sub _profile {
239 18348     18348   35205 my ($self) = @_;
240              
241 18348         36520 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   32321 my ($self, $policy_name, $policy_config) = @_;
250              
251 15272         53076 $policy_config->set_profile_strictness( $self->{_profile_strictness} );
252              
253 15272         25100 my $policy = eval { $policy_name->new( %{$policy_config} ) };
  15272         22845  
  15272         131481  
254 15272         59503 _handle_policy_instantiation_exception(
255             $policy_name,
256             $policy, # Note: being used as a boolean here.
257             $EVAL_ERROR,
258             );
259              
260 15122         53116 $policy->__set_config( $policy_config );
261              
262 15122         25727 my $eval_worked = eval { $policy->__set_base_parameters(); 1; };
  15122         66863  
  15121         34546  
263 15122         46901 _handle_policy_instantiation_exception(
264             $policy_name, $eval_worked, $EVAL_ERROR,
265             );
266              
267 15121         51767 return $policy;
268             }
269              
270             sub _handle_policy_instantiation_exception {
271 30394     30394   77279 my ($policy_name, $eval_worked, $eval_error) = @_;
272              
273 30394 100       105471 if (not $eval_worked) {
274 151 50       505 if ($eval_error) {
275 151         1140 my $exception = Exception::Class->caught();
276              
277 151 100       974 if (ref $exception) {
278 149         349 $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         431576 return;
290             }
291              
292             #-----------------------------------------------------------------------------
293              
294             sub _validate_policies_in_profile {
295 3076     3076   6751 my ($self, $errors) = @_;
296              
297 3076         8555 my $profile = $self->_profile();
298 3076         8162 my %known_policies = hashify( $self->site_policy_names() );
299              
300 3076         45548 for my $policy_name ( $profile->listed_policies() ) {
301 1833 100       3460 if ( not exists $known_policies{$policy_name} ) {
302 2         7 my $message = qq{Policy "$policy_name" is not installed.};
303              
304 2 50       6 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         20 warn qq{$message\n};
313             }
314             }
315             }
316              
317 3076         31877 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 :