File Coverage

blib/lib/Perl/Critic/Policy/Documentation/RequirePodSections.pm
Criterion Covered Total %
statement 57 69 82.6
branch 15 22 68.1
condition 2 12 16.6
subroutine 16 16 100.0
pod 5 6 83.3
total 95 125 76.0


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Documentation::RequirePodSections;
2              
3 40     40   28026 use 5.010001;
  40         393  
4 40     40   218 use strict;
  40         97  
  40         960  
5 40     40   214 use warnings;
  40         99  
  40         893  
6 40     40   197 use Readonly;
  40         96  
  40         1908  
7              
8 40     40   286 use Perl::Critic::Utils qw{ :booleans :characters :severities :classification };
  40         114  
  40         2028  
9 40     40   21680 use parent 'Perl::Critic::Policy';
  40         1328  
  40         256  
10              
11             our $VERSION = '1.150';
12              
13             #-----------------------------------------------------------------------------
14              
15             Readonly::Scalar my $EXPL => [133, 138];
16              
17             Readonly::Scalar my $BOOK => 'book';
18             Readonly::Scalar my $BOOK_FIRST_EDITION => 'book_first_edition';
19             Readonly::Scalar my $MODULE_STARTER_PBP => 'module_starter_pbp';
20             Readonly::Scalar my $M_S_PBP_0_0_3 => 'module_starter_pbp_0_0_3';
21              
22             Readonly::Scalar my $DEFAULT_SOURCE => $BOOK_FIRST_EDITION;
23              
24             Readonly::Hash my %SOURCE_TRANSLATION => (
25             $BOOK => $BOOK_FIRST_EDITION,
26             $BOOK_FIRST_EDITION => $BOOK_FIRST_EDITION,
27             $MODULE_STARTER_PBP => $M_S_PBP_0_0_3,
28             $M_S_PBP_0_0_3 => $M_S_PBP_0_0_3,
29             );
30              
31             Readonly::Scalar my $EN_AU => 'en_AU';
32             Readonly::Scalar my $EN_US => 'en_US';
33             Readonly::Scalar my $ORIGINAL_MODULE_VERSION => 'original';
34              
35             Readonly::Hash my %SOURCE_DEFAULT_LANGUAGE => (
36             $BOOK_FIRST_EDITION => $ORIGINAL_MODULE_VERSION,
37             $M_S_PBP_0_0_3 => $EN_AU,
38             );
39              
40             Readonly::Scalar my $BOOK_FIRST_EDITION_US_LIB_SECTIONS =>
41             [
42             'NAME',
43             'VERSION',
44             'SYNOPSIS',
45             'DESCRIPTION',
46             'SUBROUTINES/METHODS',
47             'DIAGNOSTICS',
48             'CONFIGURATION AND ENVIRONMENT',
49             'DEPENDENCIES',
50             'INCOMPATIBILITIES',
51             'BUGS AND LIMITATIONS',
52             'AUTHOR',
53             'LICENSE AND COPYRIGHT',
54             ];
55              
56             Readonly::Hash my %DEFAULT_LIB_SECTIONS => (
57             $BOOK_FIRST_EDITION => {
58             $ORIGINAL_MODULE_VERSION => $BOOK_FIRST_EDITION_US_LIB_SECTIONS,
59             $EN_AU => [
60             'NAME',
61             'VERSION',
62             'SYNOPSIS',
63             'DESCRIPTION',
64             'SUBROUTINES/METHODS',
65             'DIAGNOSTICS',
66             'CONFIGURATION AND ENVIRONMENT',
67             'DEPENDENCIES',
68             'INCOMPATIBILITIES',
69             'BUGS AND LIMITATIONS',
70             'AUTHOR',
71             'LICENCE AND COPYRIGHT',
72             ],
73             $EN_US => $BOOK_FIRST_EDITION_US_LIB_SECTIONS,
74             },
75             $M_S_PBP_0_0_3 => {
76             $EN_AU => [
77             'NAME',
78             'VERSION',
79             'SYNOPSIS',
80             'DESCRIPTION',
81             'INTERFACE',
82             'DIAGNOSTICS',
83             'CONFIGURATION AND ENVIRONMENT',
84             'DEPENDENCIES',
85             'INCOMPATIBILITIES',
86             'BUGS AND LIMITATIONS',
87             'AUTHOR',
88             'LICENCE AND COPYRIGHT',
89             'DISCLAIMER OF WARRANTY',
90             ],
91             $EN_US => [
92             'NAME',
93             'VERSION',
94             'SYNOPSIS',
95             'DESCRIPTION',
96             'INTERFACE',
97             'DIAGNOSTICS',
98             'CONFIGURATION AND ENVIRONMENT',
99             'DEPENDENCIES',
100             'INCOMPATIBILITIES',
101             'BUGS AND LIMITATIONS',
102             'AUTHOR',
103             'LICENSE AND COPYRIGHT',
104             'DISCLAIMER OF WARRANTY'
105             ],
106             },
107             );
108              
109             Readonly::Hash my %DEFAULT_SCRIPT_SECTIONS => (
110             $BOOK_FIRST_EDITION => {
111             $ORIGINAL_MODULE_VERSION => [
112             'NAME',
113             'USAGE',
114             'DESCRIPTION',
115             'REQUIRED ARGUMENTS',
116             'OPTIONS',
117             'DIAGNOSTICS',
118             'EXIT STATUS',
119             'CONFIGURATION',
120             'DEPENDENCIES',
121             'INCOMPATIBILITIES',
122             'BUGS AND LIMITATIONS',
123             'AUTHOR',
124             'LICENSE AND COPYRIGHT',
125             ],
126             $EN_AU => [
127             'NAME',
128             'VERSION',
129             'USAGE',
130             'REQUIRED ARGUMENTS',
131             'OPTIONS',
132             'DESCRIPTION',
133             'DIAGNOSTICS',
134             'CONFIGURATION AND ENVIRONMENT',
135             'DEPENDENCIES',
136             'INCOMPATIBILITIES',
137             'BUGS AND LIMITATIONS',
138             'AUTHOR',
139             'LICENCE AND COPYRIGHT',
140             ],
141             $EN_US => [
142             'NAME',
143             'VERSION',
144             'USAGE',
145             'REQUIRED ARGUMENTS',
146             'OPTIONS',
147             'DESCRIPTION',
148             'DIAGNOSTICS',
149             'CONFIGURATION AND ENVIRONMENT',
150             'DEPENDENCIES',
151             'INCOMPATIBILITIES',
152             'BUGS AND LIMITATIONS',
153             'AUTHOR',
154             'LICENSE AND COPYRIGHT',
155             ],
156             },
157             $M_S_PBP_0_0_3 => {
158             $EN_AU => [
159             'NAME',
160             'VERSION',
161             'USAGE',
162             'REQUIRED ARGUMENTS',
163             'OPTIONS',
164             'DESCRIPTION',
165             'DIAGNOSTICS',
166             'CONFIGURATION AND ENVIRONMENT',
167             'DEPENDENCIES',
168             'INCOMPATIBILITIES',
169             'BUGS AND LIMITATIONS',
170             'AUTHOR',
171             'LICENCE AND COPYRIGHT',
172             'DISCLAIMER OF WARRANTY',
173             ],
174             $EN_US => [
175             'NAME',
176             'VERSION',
177             'USAGE',
178             'REQUIRED ARGUMENTS',
179             'OPTIONS',
180             'DESCRIPTION',
181             'DIAGNOSTICS',
182             'CONFIGURATION AND ENVIRONMENT',
183             'DEPENDENCIES',
184             'INCOMPATIBILITIES',
185             'BUGS AND LIMITATIONS',
186             'AUTHOR',
187             'LICENSE AND COPYRIGHT',
188             'DISCLAIMER OF WARRANTY',
189             ],
190             },
191             );
192              
193             #-----------------------------------------------------------------------------
194              
195             sub supported_parameters {
196             return (
197             {
198 93     93 0 2677 name => 'lib_sections',
199             description => 'The sections to require for modules (separated by qr/\s* [|] \s*/xms).',
200             default_string => $EMPTY,
201             parser => \&_parse_lib_sections,
202             },
203             {
204             name => 'script_sections',
205             description => 'The sections to require for programs (separated by qr/\s* [|] \s*/xms).',
206             default_string => $EMPTY,
207             parser => \&_parse_script_sections,
208             },
209             {
210             name => 'source',
211             description => 'The origin of sections to use.',
212             default_string => $DEFAULT_SOURCE,
213             behavior => 'enumeration',
214             enumeration_values => [ keys %SOURCE_TRANSLATION ],
215             },
216             {
217             name => 'language',
218             description => 'The spelling of sections to use.',
219             default_string => $EMPTY,
220             behavior => 'enumeration',
221             enumeration_values => [ $EN_AU, $EN_US ],
222             },
223             );
224             }
225              
226 73     73 1 301 sub default_severity { return $SEVERITY_LOW }
227 86     86 1 338 sub default_themes { return qw(core pbp maintenance) }
228 30     30 1 100 sub applies_to { return 'PPI::Document' }
229              
230             #-----------------------------------------------------------------------------
231              
232             sub _parse_sections {
233 5     5   14 my $config_string = shift;
234              
235 5         29 my @sections = split m{ \s* [|] \s* }xms, $config_string;
236              
237 5         29 return map { uc } @sections; # Normalize CaSe!
  4         15  
238             }
239              
240             sub _parse_lib_sections {
241 91     91   402 my ($self, $parameter, $config_string) = @_;
242              
243 91 100       388 if ( defined $config_string ) {
244 3         31 $self->{_lib_sections} = [ _parse_sections( $config_string ) ];
245             }
246              
247 91         309 return;
248             }
249              
250             sub _parse_script_sections {
251 91     91   328 my ($self, $parameter, $config_string) = @_;
252              
253 91 100       340 if ( defined $config_string ) {
254 2         15 $self->{_script_sections} = [ _parse_sections( $config_string ) ];
255             }
256              
257 91         239 return;
258             }
259              
260             #-----------------------------------------------------------------------------
261              
262             sub initialize_if_enabled {
263 53     53 1 181 my ($self, $config) = @_;
264              
265 53         194 my $source = $self->{_source};
266 53 50 33     547 if ( not defined $source or not defined $DEFAULT_LIB_SECTIONS{$source} ) {
267 0         0 $source = $DEFAULT_SOURCE;
268             }
269              
270 53         668 my $language = $self->{_language};
271 53 50 33     305 if (
272             not defined $language
273             or not defined $DEFAULT_LIB_SECTIONS{$source}{$language}
274             ) {
275 53         974 $language = $SOURCE_DEFAULT_LANGUAGE{$source};
276             }
277              
278 53 50       542 if ( not $self->_sections_specified('_lib_sections') ) {
279 53         180 $self->{_lib_sections} = $DEFAULT_LIB_SECTIONS{$source}{$language};
280             }
281 53 50       725 if ( not $self->_sections_specified('_script_sections') ) {
282             $self->{_script_sections} =
283 53         241 $DEFAULT_SCRIPT_SECTIONS{$source}{$language};
284             }
285              
286 53         756 return $TRUE;
287             }
288              
289             sub _sections_specified {
290 106     106   285 my ( $self, $sections_key ) = @_;
291              
292 106         244 my $sections = $self->{$sections_key};
293              
294 106 100       430 return 0 if not defined $sections;
295              
296 4         10 return scalar @{ $sections };
  4         13  
297             }
298              
299             #-----------------------------------------------------------------------------
300              
301             sub violates {
302 30     30 1 149 my ( $self, $elem, $doc ) = @_;
303              
304             # This policy does not apply unless there is some real code in the
305             # file. For example, if this file is just pure POD, then
306             # presumably this file is ancillary documentation and you can use
307             # whatever headings you want.
308 30 100       205 return if ! $doc->schild(0);
309              
310 28         538 my %found_sections;
311             my @violations;
312              
313             my @required_sections =
314             $doc->is_program()
315 1         5 ? @{ $self->{_script_sections} }
316 28 100       122 : @{ $self->{_lib_sections} };
  27         187  
317              
318 28         1706 my $pods_ref = $doc->find('PPI::Token::Pod');
319 28 50       218 return if not $pods_ref;
320              
321             # Round up the names of all the =head1 sections
322 0           my $pod_of_record;
323 0           for my $pod ( @{ $pods_ref } ) {
  0            
324 0           for my $found ( $pod =~ m{ ^ =head1 \s+ ( .+? ) \s* $ }gxms ) {
325             # Use first matching POD as POD of record (RT #59268)
326 0   0       $pod_of_record ||= $pod;
327             #Leading/trailing whitespace is already removed
328 0           $found_sections{ uc $found } = 1;
329             }
330             }
331              
332             # Compare the required sections against those we found
333 0           for my $required ( @required_sections ) {
334 0 0         if ( not exists $found_sections{$required} ) {
335 0           my $desc = qq{Missing "$required" section in POD};
336             # Report any violations against POD of record rather than whole
337             # document (the point of RT #59268)
338             # But if there are no =head1 records at all, rat out the
339             # first pod found, as being better than blowing up. RT #67231
340 0   0       push @violations, $self->violation( $desc, $EXPL,
341             $pod_of_record || $pods_ref->[0] );
342             }
343             }
344              
345 0           return @violations;
346             }
347              
348             1;
349              
350             __END__
351              
352             #-----------------------------------------------------------------------------
353              
354             =pod
355              
356             =for stopwords licence
357              
358             =head1 NAME
359              
360             Perl::Critic::Policy::Documentation::RequirePodSections - Organize your POD into the customary sections.
361              
362              
363             =head1 AFFILIATION
364              
365             This Policy is part of the core L<Perl::Critic|Perl::Critic>
366             distribution.
367              
368              
369             =head1 DESCRIPTION
370              
371             This Policy requires your POD to contain certain C<=head1> sections.
372             If the file doesn't contain any POD at all, then this Policy does not
373             apply. Tools like L<Module::Starter|Module::Starter> make it really
374             easy to ensure that every module has the same documentation framework,
375             and they can save you lots of keystrokes.
376              
377              
378             =head1 DEFAULTS
379              
380             Different POD sections are required, depending on whether the file is
381             a library or program (which is determined by the presence or absence
382             of a perl shebang line).
383              
384             Default Required POD Sections
385              
386             Perl Libraries Perl Programs
387             ----------------------------- ---------------------
388             NAME NAME
389             VERSION
390             SYNOPSIS USAGE
391             DESCRIPTION DESCRIPTION
392             SUBROUTINES/METHODS REQUIRED ARGUMENTS
393             OPTIONS
394             DIAGNOSTICS DIAGNOSTICS
395             EXIT STATUS
396             CONFIGURATION AND ENVIRONMENT CONFIGURATION
397             DEPENDENCIES DEPENDENCIES
398             INCOMPATIBILITIES INCOMPATIBILITIES
399             BUGS AND LIMITATIONS BUGS AND LIMITATIONS
400             AUTHOR AUTHOR
401             LICENSE AND COPYRIGHT LICENSE AND COPYRIGHT
402              
403              
404             =head1 CONFIGURATION
405              
406             The default sections above are derived from Damian Conway's I<Perl
407             Best Practices> book. Since the book has been published, Conway has
408             released L<Module::Starter::PBP|Module::Starter::PBP>, which has
409             different names for some of the sections, and adds some more. Also,
410             the book and module use Australian spelling, while the authors of this
411             module have previously used American spelling. To sort this all out,
412             there are a couple of options that can be used: C<source> and
413             C<language>.
414              
415             The C<source> option has two generic values, C<book> and
416             C<module_starter_pbp>, and two version-specific values,
417             C<book_first_edition> and C<module_starter_pbp_0_0_3>. Currently, the
418             generic values map to the corresponding version-specific values, but
419             may change as new versions of the book and module are released, so use
420             these if you want to keep up with the latest and greatest. If you
421             want things to remain stable, use the version-specific values.
422              
423             The C<language> option has a default, unnamed value but also accepts
424             values of C<en_AU> and C<en_US>. The reason the unnamed value exists
425             is because the default values for programs don't actually match the
426             book, even taking spelling into account, i.e. C<CONFIGURATION> instead
427             of C<CONFIGURATION AND ENVIRONMENT>, the removal of C<VERSION>, and
428             the addition of C<EXIT STATUS>. To get precisely the sections as
429             specified in the book, put the following in your F<.perlcriticrc>
430             file:
431              
432             [Documentation::RequirePodSections]
433             source = book_first_edition
434             language = en_AU
435              
436             If you want to use
437              
438             [Documentation::RequirePodSections]
439             source = module_starter_pbp
440             language = en_US
441              
442             you will need to modify your F<~/.module-starter/PBP/Module.pm>
443             template because it is generated using Australian spelling.
444              
445             Presently, the difference between C<en_AU> and C<en_US> is in how the
446             word "licence" is spelled.
447              
448             The sections required for modules and programs can be independently
449             customized, overriding any values for C<source> and C<language>, by
450             giving values for C<script_sections> and C<lib_sections> of a string
451             of pipe-delimited required POD section names. An example of entries
452             in a F<.perlcriticrc> file:
453              
454             [Documentation::RequirePodSections]
455             lib_sections = NAME | SYNOPSIS | BUGS AND LIMITATIONS | AUTHOR
456             script_sections = NAME | USAGE | OPTIONS | EXIT STATUS | AUTHOR
457              
458              
459             =head1 LIMITATIONS
460              
461             Currently, this Policy does not look for the required POD sections
462             below the C<=head1> level. Also, it does not require the sections to
463             appear in any particular order.
464              
465             This Policy applies to the entire document, but can be disabled for a
466             particular document by a C<## no critic (RequirePodSections)> annotation
467             anywhere between the beginning of the document and the first POD section
468             containing a C<=head1>, the C<__END__> (if any), or the C<__DATA__> (if any),
469             whichever comes first.
470              
471              
472             =head1 AUTHOR
473              
474             Jeffrey Ryan Thalhammer <jeff@imaginative-software.com>
475              
476              
477             =head1 COPYRIGHT
478              
479             Copyright (c) 2006-2011 Imaginative Software Systems. All rights reserved.
480              
481             This program is free software; you can redistribute it and/or modify
482             it under the same terms as Perl itself. The full text of this license
483             can be found in the LICENSE file included with this module
484              
485             =cut
486              
487             # Local Variables:
488             # mode: cperl
489             # cperl-indent-level: 4
490             # fill-column: 78
491             # indent-tabs-mode: nil
492             # c-indentation-style: bsd
493             # End:
494             # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :