File Coverage

blib/lib/Perl/Critic/UserProfile.pm
Criterion Covered Total %
statement 120 128 93.7
branch 16 26 61.5
condition 18 30 60.0
subroutine 29 30 96.6
pod 8 8 100.0
total 191 222 86.0


line stmt bran cond sub pod time code
1             package Perl::Critic::UserProfile;
2              
3 40     40   17137 use 5.010001;
  40         232  
4 40     40   285 use strict;
  40         118  
  40         832  
5 40     40   243 use warnings;
  40         135  
  40         963  
6              
7 40     40   3453 use Readonly;
  40         23978  
  40         2055  
8              
9 40     40   21405 use Config::Tiny qw();
  40         46007  
  40         939  
10 40     40   350 use File::Spec qw();
  40         119  
  40         708  
11              
12 40     40   17703 use Perl::Critic::OptionsProcessor qw();
  40         140  
  40         1323  
13 40     40   345 use Perl::Critic::Utils qw{ $EMPTY policy_long_name policy_short_name };
  40         106  
  40         4161  
14 40     40   386 use Perl::Critic::Exception::Fatal::Internal qw{ throw_internal };
  40         105  
  40         1823  
15 40     40   3953 use Perl::Critic::Exception::Configuration::Generic qw{ throw_generic };
  40         126  
  40         965  
16 40     40   4662 use Perl::Critic::PolicyConfig;
  40         123  
  40         58103  
17              
18             our $VERSION = '1.150';
19              
20             #-----------------------------------------------------------------------------
21              
22             sub new {
23              
24 443     443 1 61248 my ( $class, %args ) = @_;
25 443         1220 my $self = bless {}, $class;
26 443         1817 $self->_init( %args );
27 439         1413 return $self;
28             }
29              
30             #-----------------------------------------------------------------------------
31              
32             sub _init {
33              
34 443     443   1196 my ( $self, %args ) = @_;
35             # The profile can be defined, undefined, or an empty string.
36 443   66     1615 my $profile = $args{-profile} // _find_profile_path();
37 443         1472 $self->_load_profile( $profile );
38 439         1312 $self->_set_options_processor();
39 439         1099 return $self;
40             }
41              
42             #-----------------------------------------------------------------------------
43              
44             sub options_processor {
45              
46 2111     2111 1 3729 my ($self) = @_;
47 2111         6490 return $self->{_options_processor};
48             }
49              
50             #-----------------------------------------------------------------------------
51              
52             sub policy_params {
53              
54 12362     12362 1 22348 my ( $self, $policy ) = @_;
55              
56 12362         24521 my $short_name = policy_short_name($policy);
57              
58 12362         28849 return Perl::Critic::PolicyConfig->new(
59             $short_name,
60             $self->raw_policy_params($policy),
61             );
62             }
63              
64             #-----------------------------------------------------------------------------
65              
66             sub raw_policy_params {
67              
68 12374     12374 1 21581 my ( $self, $policy ) = @_;
69 12374         21778 my $profile = $self->{_profile};
70 12374   33     42553 my $long_name = ref $policy || policy_long_name( $policy );
71 12374         25061 my $short_name = policy_short_name( $long_name );
72              
73             return
74             $profile->{$short_name}
75             || $profile->{$long_name}
76             || $profile->{"-$short_name"}
77 12374   100     127156 || $profile->{"-$long_name"}
78             || {};
79             }
80              
81             #-----------------------------------------------------------------------------
82              
83             sub policy_is_disabled {
84              
85 10886     10886 1 17398 my ( $self, $policy ) = @_;
86 10886         15949 my $profile = $self->{_profile};
87 10886   66     31821 my $long_name = ref $policy || policy_long_name( $policy );
88 10886         27599 my $short_name = policy_short_name( $long_name );
89              
90             return exists $profile->{"-$short_name"}
91 10886   100     67593 || exists $profile->{"-$long_name"};
92             }
93              
94             #-----------------------------------------------------------------------------
95              
96             sub policy_is_enabled {
97              
98 10886     10886 1 17226 my ( $self, $policy ) = @_;
99 10886         15801 my $profile = $self->{_profile};
100 10886   66     23147 my $long_name = ref $policy || policy_long_name( $policy );
101 10886         21392 my $short_name = policy_short_name( $long_name );
102              
103             return exists $profile->{$short_name}
104 10886   66     47482 || exists $profile->{$long_name};
105             }
106              
107             #-----------------------------------------------------------------------------
108              
109             sub listed_policies {
110              
111 434     434 1 1161 my ( $self, $policy ) = @_;
112 434         744 my @normalized_policy_names;
113              
114 434         790 for my $policy_name ( sort keys %{$self->{_profile}} ) {
  434         2720  
115 1833         2900 $policy_name =~ s/\A - //xmso; #Chomp leading "-"
116 1833         3320 my $policy_long_name = policy_long_name( $policy_name );
117 1833         3200 push @normalized_policy_names, $policy_long_name;
118             }
119              
120 434         1621 return @normalized_policy_names;
121             }
122              
123             #-----------------------------------------------------------------------------
124              
125             sub source {
126 3493     3493 1 5507 my ( $self ) = @_;
127              
128 3493         6469 return $self->{_source};
129             }
130              
131             sub _set_source {
132 3     3   10 my ( $self, $source ) = @_;
133              
134 3         15 $self->{_source} = $source;
135              
136 3         13 return;
137             }
138              
139             #-----------------------------------------------------------------------------
140             # Begin PRIVATE methods
141              
142             Readonly::Hash my %LOADER_FOR => (
143             ARRAY => \&_load_profile_from_array,
144             DEFAULT => \&_load_profile_from_file,
145             HASH => \&_load_profile_from_hash,
146             SCALAR => \&_load_profile_from_string,
147             );
148              
149             sub _load_profile {
150              
151 443     443   981 my ( $self, $profile ) = @_;
152              
153 443   100     1845 my $ref_type = ref $profile || 'DEFAULT';
154 443         2654 my $loader = $LOADER_FOR{$ref_type};
155              
156 443 100       4264 if (not $loader) {
157 1         8 throw_internal qq{Can't load UserProfile from type "$ref_type"};
158             }
159              
160 442         1261 $self->{_profile} = $loader->($self, $profile);
161 439         887 return $self;
162             }
163              
164             #-----------------------------------------------------------------------------
165              
166             sub _set_options_processor {
167              
168 439     439   922 my ($self) = @_;
169 439         845 my $profile = $self->{_profile};
170 439   100     1792 my $defaults = delete $profile->{__defaults__} || {};
171             $self->{_options_processor} =
172 439         878 Perl::Critic::OptionsProcessor->new( %{ $defaults } );
  439         2358  
173 439         1184 return $self;
174             }
175              
176             #-----------------------------------------------------------------------------
177              
178             sub _load_profile_from_file {
179 385     385   789 my ( $self, $file ) = @_;
180              
181             # Handle special cases.
182 385 100       953 return {} if not defined $file;
183 354 100       857 return {} if $file eq $EMPTY;
184 351 100       1212 return {} if $file eq 'NONE';
185              
186 3         15 $self->_set_source( $file );
187              
188 3         30 my $profile = Config::Tiny->read( $file );
189 3 100       3183 if (not defined $profile) {
190 1         5 my $errstr = Config::Tiny::errstr();
191 1         10 throw_generic
192             message => qq{Could not parse profile "$file": $errstr},
193             source => $file;
194             }
195              
196 2         15 _fix_defaults_key( $profile );
197              
198 2         7 return $profile;
199             }
200              
201             #-----------------------------------------------------------------------------
202              
203             sub _load_profile_from_array {
204 1     1   4 my ( $self, $array_ref ) = @_;
205 1         3 my $joined = join qq{\n}, @{ $array_ref };
  1         5  
206 1         14 my $profile = Config::Tiny->read_string( $joined );
207              
208 1 50       104 if (not defined $profile) {
209 0         0 throw_generic 'Profile error: ' . Config::Tiny::errstr();
210             }
211              
212 1         7 _fix_defaults_key( $profile );
213              
214 1         3 return $profile;
215             }
216              
217             #-----------------------------------------------------------------------------
218              
219             sub _load_profile_from_string {
220 5     5   13 my ( $self, $string ) = @_;
221 5         12 my $profile = Config::Tiny->read_string( ${ $string } );
  5         30  
222              
223 5 100       19328 if (not defined $profile) {
224 2         7 throw_generic 'Profile error: ' . Config::Tiny::errstr();
225             }
226              
227 3         13 _fix_defaults_key( $profile );
228              
229 3         10 return $profile;
230             }
231              
232             #-----------------------------------------------------------------------------
233              
234             sub _load_profile_from_hash {
235 51     51   180 my ( $self, $hash_ref ) = @_;
236 51         198 return $hash_ref;
237             }
238              
239             #-----------------------------------------------------------------------------
240              
241             sub _find_profile_path {
242              
243             #Check explicit environment setting
244 1 50   1   2190 return $ENV{PERLCRITIC} if exists $ENV{PERLCRITIC};
245              
246             #Define default filename
247 0         0 my $rc_file = '.perlcriticrc';
248              
249             #Check current directory
250 0 0       0 return $rc_file if -f $rc_file;
251              
252             #Check home directory
253 0 0       0 if ( my $home_dir = _find_home_dir() ) {
254 0         0 my $path = File::Spec->catfile( $home_dir, $rc_file );
255 0 0       0 return $path if -f $path;
256             }
257              
258             #No profile defined
259 0         0 return;
260             }
261              
262             #-----------------------------------------------------------------------------
263              
264             sub _find_home_dir {
265             # This logic is taken from File::HomeDir::Tiny.
266             return
267             ($^O eq 'MSWin32') && ("$]" < 5.016) ## no critic ( Variables::ProhibitPunctuationVars ValuesAndExpressions::ProhibitMagicNumbers ValuesAndExpressions::ProhibitMismatchedOperators )
268             ? ($ENV{HOME} || $ENV{USERPROFILE})
269 0 0 0 0   0 : (<~>)[0];
      0        
270             }
271              
272             #-----------------------------------------------------------------------------
273              
274             # !$%@$%^ Config::Tiny uses a completely non-descriptive name for global
275             # values.
276             sub _fix_defaults_key {
277 6     6   16 my ( $profile ) = @_;
278              
279 6         15 my $defaults = delete $profile->{_};
280 6 100       21 if ($defaults) {
281 3         10 $profile->{__defaults__} = $defaults;
282             }
283              
284 6         12 return;
285             }
286              
287             1;
288              
289             __END__
290              
291             #-----------------------------------------------------------------------------
292              
293             =pod
294              
295             =for stopwords UserProfile
296              
297             =head1 NAME
298              
299             Perl::Critic::UserProfile - The contents of the user's profile, often F<.perlcriticrc>.
300              
301              
302             =head1 DESCRIPTION
303              
304             This is a helper class that encapsulates the contents of the user's
305             profile, which is usually stored in a F<.perlcriticrc> file. There are
306             no user-serviceable parts here.
307              
308              
309             =head1 INTERFACE SUPPORT
310              
311             This is considered to be a non-public class. Its interface is subject
312             to change without notice.
313              
314              
315             =head1 CONSTRUCTOR
316              
317             =over
318              
319             =item C<< new( -profile => $p ) >>
320              
321             B<-profile> is the path to the user's profile. If -profile is not
322             defined, then it looks for the profile at F<./.perlcriticrc> and then
323             F<$HOME/.perlcriticrc>. If neither of those files exists, then the
324             UserProfile is created with default values.
325              
326             This object does not take into account any command-line overrides;
327             L<Perl::Critic::Config|Perl::Critic::Config> does that.
328              
329              
330             =back
331              
332              
333             =head1 METHODS
334              
335             =over
336              
337             =item C< options_processor() >
338              
339             Returns the
340             L<Perl::Critic::OptionsProcessor|Perl::Critic::OptionsProcessor>
341             object for this UserProfile.
342              
343              
344             =item C< policy_is_disabled( $policy ) >
345              
346             Given a reference to a L<Perl::Critic::Policy|Perl::Critic::Policy>
347             object or the name of one, returns true if the user has disabled that
348             policy in their profile.
349              
350              
351             =item C< policy_is_enabled( $policy ) >
352              
353             Given a reference to a L<Perl::Critic::Policy|Perl::Critic::Policy>
354             object or the name of one, returns true if the user has explicitly
355             enabled that policy in their user profile.
356              
357              
358             =item C< policy_params( $policy ) >
359              
360             Given a reference to a L<Perl::Critic::Policy|Perl::Critic::Policy>
361             object or the name of one, returns a
362             L<Perl::Critic::PolicyConfig|Perl::Critic::PolicyConfig> for the
363             user's configuration parameters for that policy.
364              
365              
366             =item C< raw_policy_params( $policy ) >
367              
368             Given a reference to a L<Perl::Critic::Policy|Perl::Critic::Policy>
369             object or the name of one, returns a reference to a hash of the user's
370             configuration parameters for that policy.
371              
372              
373             =item C< listed_policies() >
374              
375             Returns a list of the names of all the Policies that are mentioned in
376             the profile. The Policy names will be fully qualified (e.g.
377             Perl::Critic::Foo).
378              
379              
380             =item C< source() >
381              
382             The place where the profile information came from, if available.
383             Usually the path to a F<.perlcriticrc>.
384              
385              
386             =back
387              
388              
389             =head1 SEE ALSO
390              
391             L<Perl::Critic::Config|Perl::Critic::Config>,
392             L<Perl::Critic::OptionsProcessor|Perl::Critic::OptionsProcessor>
393              
394              
395             =head1 AUTHOR
396              
397             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
398              
399              
400             =head1 COPYRIGHT
401              
402             Copyright (c) 2005-2023 Imaginative Software Systems.
403              
404             This program is free software; you can redistribute it and/or modify
405             it under the same terms as Perl itself. The full text of this license
406             can be found in the LICENSE file included with this module.
407              
408             =cut
409              
410             # Local Variables:
411             # mode: cperl
412             # cperl-indent-level: 4
413             # fill-column: 78
414             # indent-tabs-mode: nil
415             # c-indentation-style: bsd
416             # End:
417             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :