File Coverage

blib/lib/Perl/Critic/Policy/Documentation/RequirePodSections.pm
Criterion Covered Total %
statement 69 70 98.5
branch 20 22 90.9
condition 6 12 50.0
subroutine 16 16 100.0
pod 5 6 83.3
total 116 126 92.0


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Documentation::RequirePodSections;
2              
3 40     40   28505 use 5.010001;
  40         168  
4 40     40   241 use strict;
  40         102  
  40         864  
5 40     40   212 use warnings;
  40         107  
  40         1021  
6 40     40   215 use Readonly;
  40         124  
  40         2251  
7              
8 40     40   290 use Perl::Critic::Utils qw{ :booleans :characters :severities :classification };
  40         88  
  40         2273  
9 40     40   22076 use parent 'Perl::Critic::Policy';
  40         104  
  40         245  
10              
11             our $VERSION = '1.146';
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 102     102 0 2905 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 117     117 1 559 sub default_severity { return $SEVERITY_LOW }
227 86     86 1 425 sub default_themes { return qw(core pbp maintenance) }
228 39     39 1 118 sub applies_to { return 'PPI::Document' }
229              
230             #-----------------------------------------------------------------------------
231              
232             sub _parse_sections {
233 8     8   19 my $config_string = shift;
234              
235 8         42 my @sections = split m{ \s* [|] \s* }xms, $config_string;
236              
237 8         33 return map { uc } @sections; # Normalize CaSe!
  9         35  
238             }
239              
240             sub _parse_lib_sections {
241 100     100   471 my ($self, $parameter, $config_string) = @_;
242              
243 100 100       425 if ( defined $config_string ) {
244 5         28 $self->{_lib_sections} = [ _parse_sections( $config_string ) ];
245             }
246              
247 100         318 return;
248             }
249              
250             sub _parse_script_sections {
251 100     100   446 my ($self, $parameter, $config_string) = @_;
252              
253 100 100       433 if ( defined $config_string ) {
254 3         24 $self->{_script_sections} = [ _parse_sections( $config_string ) ];
255             }
256              
257 100         275 return;
258             }
259              
260             #-----------------------------------------------------------------------------
261              
262             sub initialize_if_enabled {
263 62     62 1 263 my ($self, $config) = @_;
264              
265 62         217 my $source = $self->{_source};
266 62 50 33     664 if ( not defined $source or not defined $DEFAULT_LIB_SECTIONS{$source} ) {
267 0         0 $source = $DEFAULT_SOURCE;
268             }
269              
270 62         817 my $language = $self->{_language};
271 62 50 33     411 if (
272             not defined $language
273             or not defined $DEFAULT_LIB_SECTIONS{$source}{$language}
274             ) {
275 62         1158 $language = $SOURCE_DEFAULT_LANGUAGE{$source};
276             }
277              
278 62 100       751 if ( not $self->_sections_specified('_lib_sections') ) {
279 60         229 $self->{_lib_sections} = $DEFAULT_LIB_SECTIONS{$source}{$language};
280             }
281 62 100       1672 if ( not $self->_sections_specified('_script_sections') ) {
282             $self->{_script_sections} =
283 61         297 $DEFAULT_SCRIPT_SECTIONS{$source}{$language};
284             }
285              
286 62         985 return $TRUE;
287             }
288              
289             sub _sections_specified {
290 124     124   352 my ( $self, $sections_key ) = @_;
291              
292 124         296 my $sections = $self->{$sections_key};
293              
294 124 100       596 return 0 if not defined $sections;
295              
296 7         14 return scalar @{ $sections };
  7         30  
297             }
298              
299             #-----------------------------------------------------------------------------
300              
301             sub violates {
302 39     39 1 134 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 39 100       293 return if ! $doc->schild(0);
309              
310 36         726 my %found_sections = ();
311 36         87 my @violations = ();
312              
313             my @required_sections =
314             $doc->is_program()
315 5         34 ? @{ $self->{_script_sections} }
316 36 100       157 : @{ $self->{_lib_sections} };
  31         224  
317              
318 36         2337 my $pods_ref = $doc->find('PPI::Token::Pod');
319 36 100       231 return if not $pods_ref;
320              
321             # Round up the names of all the =head1 sections
322 7         15 my $pod_of_record;
323 7         16 for my $pod ( @{ $pods_ref } ) {
  7         22  
324 9         28 for my $found ( $pod =~ m{ ^ =head1 \s+ ( .+? ) \s* $ }gxms ) {
325             # Use first matching POD as POD of record (RT #59268)
326 15   66     129 $pod_of_record ||= $pod;
327             #Leading/trailing whitespace is already removed
328 15         53 $found_sections{ uc $found } = 1;
329             }
330             }
331              
332             # Compare the required sections against those we found
333 7         24 for my $required ( @required_sections ) {
334 55 100       140 if ( not exists $found_sections{$required} ) {
335 44         123 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 44   66     218 push @violations, $self->violation( $desc, $EXPL,
341             $pod_of_record || $pods_ref->[0] );
342             }
343             }
344              
345 7         41 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 :