File Coverage

blib/lib/Perl/Critic/Policy/CodeLayout/RequireTidyCode.pm
Criterion Covered Total %
statement 63 64 98.4
branch 8 12 66.6
condition 3 6 50.0
subroutine 17 17 100.0
pod 5 6 83.3
total 96 105 91.4


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::CodeLayout::RequireTidyCode;
2              
3 40     40   27652 use 5.010001;
  40         211  
4 40     40   278 use strict;
  40         127  
  40         881  
5 40     40   280 use warnings;
  40         179  
  40         1207  
6              
7 40     40   298 use English qw(-no_match_vars);
  40         116  
  40         396  
8 40     40   17318 use IO::Handle ();
  40         160  
  40         954  
9 40     40   264 use Readonly;
  40         138  
  40         1946  
10              
11 40     40   49440 use Perl::Tidy qw< >;
  40         12044823  
  40         1967  
12              
13 40     40   549 use Perl::Critic::Exception::Fatal::Generic qw{ throw_generic };
  40         108  
  40         2866  
14 40     40   398 use Perl::Critic::Utils qw{ :booleans :characters :severities };
  40         115  
  40         2703  
15 40     40   14689 use parent 'Perl::Critic::Policy';
  40         182  
  40         305  
16              
17             our $VERSION = '1.150';
18              
19             #-----------------------------------------------------------------------------
20              
21             Readonly::Scalar my $DESC => q{Code is not tidy};
22             Readonly::Scalar my $EXPL => [ 33 ];
23              
24             #-----------------------------------------------------------------------------
25              
26             sub supported_parameters {
27             return (
28             {
29 96     96 0 2089 name => 'perltidyrc',
30             description => 'The Perl::Tidy configuration file to use, if any.',
31             default_string => undef,
32             },
33             );
34             }
35              
36 75     75 1 343 sub default_severity { return $SEVERITY_LOWEST }
37 84     84 1 423 sub default_themes { return qw(core pbp cosmetic) }
38 6     6 1 22 sub applies_to { return 'PPI::Document' }
39              
40             #-----------------------------------------------------------------------------
41              
42             sub initialize_if_enabled {
43 26     26 1 119 my ($self, $config) = @_;
44              
45             # Set configuration if defined
46 26 100 66     200 if (defined $self->{_perltidyrc} && $self->{_perltidyrc} eq $EMPTY) {
47 7         20 my $rc = $EMPTY;
48 7         25 $self->{_perltidyrc} = \$rc;
49             }
50              
51 26         110 return $TRUE;
52             }
53              
54             #-----------------------------------------------------------------------------
55              
56             sub violates {
57 6     6 1 20 my ( $self, $elem, $doc ) = @_;
58              
59             # Perl::Tidy seems to produce slightly different output, depending
60             # on the trailing whitespace in the input. As best I can tell,
61             # Perl::Tidy will truncate any extra trailing newlines, and if the
62             # input has no trailing newline, then it adds one. But when you
63             # re-run it through Perl::Tidy here, that final newline gets lost,
64             # which causes the policy to insist that the code is not tidy.
65             # This only occurs when Perl::Tidy is writing the output to a
66             # scalar, but does not occur when writing to a file. I may
67             # investigate further, but for now, this seems to do the trick.
68              
69 6         38 my $source = $doc->serialize();
70 6         1716 $source =~ s{ \s+ \Z}{\n}xms;
71              
72             # Remove the shell fix code from the top of program, if applicable
73             ## no critic (ProhibitComplexRegexes)
74 6         32 my $shebang_re = qr< [#]! [^\015\012]+ [\015\012]+ >xms;
75 6         24 my $shell_re = qr<eval [ ] 'exec [ ] [^\015\012]* [ ] \$0 [ ] \$[{]1[+]"\$@"}'
76             [ \t]*[\012\015]+ [ \t]* if [^\015\012]+ [\015\012]+ >xms;
77 6         114 $source =~ s/\A ($shebang_re) $shell_re /$1/xms;
78              
79 6         28 my $dest = $EMPTY;
80 6         16 my $stderr = $EMPTY;
81              
82              
83             # Perl::Tidy gets confused if @ARGV has arguments from
84             # another program. Also, we need to override the
85             # stdout and stderr redirects that the user may have
86             # configured in their .perltidyrc file.
87             # Also override -b because we are using dest and source.
88 6         27 local @ARGV = qw(-nst -nse -nb);
89              
90             # Trap Perl::Tidy errors, just in case it dies
91 6         15 my $eval_worked = eval {
92              
93             # Beginning with version 20120619, Perl::Tidy modifies $source. So we
94             # make a copy so we can get a good comparison after tidying. Doing an
95             # s/// on $source after the fact appears not to work with previous
96             # versions of Perl::Tidy.
97 6         12 my $source_copy = $source;
98              
99             # In version 20120619 (and possibly earlier), Perl::Tidy assigns the
100             # stderr parameter directly to *STDERR. So when our $stderr goes out
101             # of scope, the handle gets closed. Subsequent calls to warn() will
102             # then cause a fatal exception. See RT #78182 for more details. In
103             # the meantime, we workaround it by localizing STDERR first.
104 6         30 local *STDERR = \*STDERR;
105              
106             # Perl::Tidy 20120619 doesn't accept a scalar ref or a glob ref
107 6 50   1   252 open my $handle, '>', \$stderr
  1         10  
  1         3  
  1         10  
108             or throw_generic "error opening scalar: $OS_ERROR";
109 6         952 $handle = *{$handle}{IO};
  6         29  
110              
111              
112             Perl::Tidy::perltidy(
113             source => \$source_copy,
114             destination => \$dest,
115             stderr => $handle,
116 6 50       134 defined $self->{_perltidyrc} ? (perltidyrc => $self->{_perltidyrc}) : (),
117             );
118              
119 6 50       982786 close $handle or throw_generic "Failed to close in memory file: $OS_ERROR";
120              
121 6         38 1;
122             };
123              
124 6 50 33     65 if ($stderr or not $eval_worked) {
125             # Looks like perltidy had problems
126 0         0 return $self->violation( 'perltidy had errors!!', $EXPL, $elem );
127             }
128              
129 6 100       44 if ( $source ne $dest ) {
130 1         14 return $self->violation( $DESC, $EXPL, $elem );
131             }
132              
133 5         63 return; #ok!
134             }
135              
136             1;
137              
138             #-----------------------------------------------------------------------------
139              
140             __END__
141              
142             =pod
143              
144             =for stopwords perltidy
145              
146             =head1 NAME
147              
148             Perl::Critic::Policy::CodeLayout::RequireTidyCode - Must run code through L<perltidy|perltidy>.
149              
150              
151             =head1 AFFILIATION
152              
153             This Policy is part of the core L<Perl::Critic|Perl::Critic>
154             distribution.
155              
156              
157             =head1 DESCRIPTION
158              
159             Conway does make specific recommendations for whitespace and
160             curly-braces in your code, but the most important thing is to adopt a
161             consistent layout, regardless of the specifics. And the easiest way
162             to do that is to use L<Perl::Tidy|Perl::Tidy>. This policy will
163             complain if your code hasn't been run through Perl::Tidy.
164              
165              
166             =head1 CONFIGURATION
167              
168             This policy can be configured to tell Perl::Tidy to use a particular
169             F<perltidyrc> file or no configuration at all. By default, Perl::Tidy
170             is told to look in its default location for configuration.
171             Perl::Critic can be told to tell Perl::Tidy to use a specific
172             configuration file by putting an entry in a F<.perlcriticrc> file like
173             this:
174              
175             [CodeLayout::RequireTidyCode]
176             perltidyrc = /usr/share/perltidy.conf
177              
178             As a special case, setting C<perltidyrc> to the empty string tells
179             Perl::Tidy not to load any configuration file at all and just use
180             Perl::Tidy's own default style.
181              
182             [CodeLayout::RequireTidyCode]
183             perltidyrc =
184              
185              
186             =head1 SEE ALSO
187              
188             L<Perl::Tidy|Perl::Tidy>
189              
190              
191             =head1 AUTHOR
192              
193             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
194              
195              
196             =head1 COPYRIGHT
197              
198             Copyright (c) 2005-2011 Imaginative Software Systems. All rights reserved.
199              
200             This program is free software; you can redistribute it and/or modify
201             it under the same terms as Perl itself. The full text of this license
202             can be found in the LICENSE file included with this module.
203              
204             =cut
205              
206             # Local Variables:
207             # mode: cperl
208             # cperl-indent-level: 4
209             # fill-column: 78
210             # indent-tabs-mode: nil
211             # c-indentation-style: bsd
212             # End:
213             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :