1Perl::Critic::DEVELOPERU(s3e)r Contributed Perl DocumentaPteiroln::Critic::DEVELOPER(3)
2
3
4

NAME

6       Perl::Critic::DEVELOPER - How to make new Perl::Critic::Policy modules
7

DESCRIPTION

9       This document describes how to create a new Policy module for
10       Perl::Critic.  It is intended for developers who wish to extend
11       Perl::Critic to enforce their own custom coding standards.  Although
12       the Perl::Critic distribution already includes a number of Policies
13       based on Damian Conway's book "Perl Best Practices", Perl::Critic is
14       not limited to his guidelines and can be used to enforce any practice,
15       preference, or style that you want to follow.  In fact, you can even
16       write Policies to enforce contradictory guidelines.  All you need to do
17       is write a corresponding Perl::Critic::Policy subclass, which may
18       require as little as 10 lines of code..
19

BACKGROUND

21       The heart of Perl::Critic is PPI, which is a parser and lexer for Perl.
22       PPI transforms a file of Perl source code into a Document Object Model
23       (DOM).  Each token in the document is represented by one of the various
24       PPI classes (for example: PPI::Token::Operator, PPI::Token::Word).  The
25       tokens are then organized into a hierarchy of structural classes (for
26       example: PPI::Statement::Expression, PPI::Structure::Subroutine).  The
27       root node of the hierarchy is the PPI::Document.
28
29       The Perl::Critic engine traverses each node in the PPI::Document tree
30       and invokes each of the Perl::Critic::Policy subclasses at the appro‐
31       priate node.  The Policy can inspect the node, look at the surrounding
32       nodes, and do whatever else it wants.  If the Policy decides that that
33       a coding standard has been violated, it returns one or more
34       Perl::Critic::Violation objects.  If there are no violations, then the
35       Policy returns nothing.
36
37       So now that we understand the basic organization of PPI and
38       Perl::Critic, lets examine one the existing Policy modules so we can
39       see how this all works.  We will pick the RequireBlockGrep.pm policy
40       because it is relatively simple but demonstrates most of the important
41       issues.  The goal of this Policy is to enforce that every call to
42       "grep" uses a block for the first argument and not an expression.  The
43       reasons for this Policy are discussed in detail in "Perl Best Prac‐
44       tices."
45

EXAMPLE POLICY

47       First, the Policy module needs to have a name.  Perl::Critic uses Mod‐
48       ule::Pluggable to automatically discover all modules that are in the
49       "Perl::Critic::Policy" namespace.  Also, we've adopted the convention
50       of grouping Policies into directories according to the table of con‐
51       tents in Conway's book "Perl Best Practices."  Since the goal of this
52       policy is to enforce the use of block arguments to "grep" and it comes
53       from the "Builtin Functions" chapter of PBP, we call it
54       "Perl::Critic::Policy::BuiltinFunctions::RequireBlockGrep".
55
56         package Perl::Critic::Policy::BuiltinFunctions::RequireBlockGrep;
57
58       Next, we set some pragmas and load the modules that we'll need.  All
59       Policy modules inherit from the Perl::Critic::Policy class, which pro‐
60       vides no-op implementations of the basic methods.  Our job is to over‐
61       ride these methods to make them do something useful.
62
63       Technically, "use strict" and "use warnings" are optional, but they are
64       necessary to make Perl::Critic self-compliant.  And we don't want
65       Perl::Critic to be a hypocrite, now do we?
66
67         use strict;
68         use warnings;
69         use Perl::Critic::Utils;
70         use Perl::Critic::Violation;
71         use base 'Perl::Critic::Policy';
72
73         our $VERSION = '0.22';
74
75       Next, we'll declare a description and explanation for this Policy.  The
76       description is always just a string that basically says "this is what's
77       wrong."  The explanation can be either a string with further details,
78       or a reference to an array of integers that correspond to page numbers
79       in the "Perl Best Practices" book.
80
81         my $desc = q{Expression form of "grep"};
82         my $expl = [169];
83
84       Most policies don't need to override the new() method provided by
85       Perl::Critic::Policy.  However, if your policy is configurable via
86       .perlcriticrc you will need to override the constructor to examine the
87       %args values.  See Perl::Critic::Policy::ControlStructures::Prohibit‐
88       CascadingIfElse for a simple example and Perl::Critic::Policy::Documen‐
89       tation::RequirePodSections for a more complex example.
90
91       Next, we define the "default_severity()" method, which should return a
92       scalar value indicating the severity of violating this Policy.  Sever‐
93       ity values range from 1 to 5, where 5 is the "most severe."  In gen‐
94       eral, level 5 is reserved for things that are frequently misused and/or
95       cause bugs.  Level 1 is for things that are highly subjective or purely
96       cosmetic.  The Perl::Critic::Utils package exports several severity
97       constants that you can use here.
98
99         sub default_severity  { return $SEVERITY_HIGH }
100
101       Likewise, the "default_themes()" method returns a list of theme names.
102       Themes are intended to be named groups of Policies.  All Policies that
103       ship with Perl::Critic have a "core" theme.  And since this Policy
104       comes directly from Damian's "Perl Best Practices" book, this Policy
105       should be a member of the "pbp" theme.
106
107         sub default_themes { return qw( core pbp ) }
108
109       As a Policy author, you can assign any themes you want to the Policy.
110       If you're publishing a suite of custom Policies, we suggest that you
111       create a unique theme that covers all the Policies in the distribution.
112       That way, users can easily enable or disable all of your policies at
113       once.
114
115       Next, we indicate what elements of the code this policy will analyze,
116       like statements or variables or conditionals or POD.  These elements
117       are specified as PPI classes such as PPI::Statement, PPI::Token::Sym‐
118       bol, PPI::Structure::Conditional or PPI::Token::Pod respectively.  The
119       applies_to() method returns a list of PPI package names.  (You can get
120       that list of available package names via "perldoc PPI".)  As
121       Perl::Critic traverses the document, it will call the "violates()"
122       method from this module whenever it encounters one of the PPI types
123       that are given here.  In this case, we just want to test calls to
124       "grep".  Since the token "grep" is a PPI::Token::Word, we return that
125       package name from the "applies_to()" method.
126
127         sub applies_to { return 'PPI::Token::Word' }
128
129       If your Policy needs to analyze several different types of elements,
130       the "applies_to" method may return the name of several PPI packages.
131       If your Policy needs to examine the file as a whole, then the
132       "applies_to" method should return PPI::Document.  Since there is only
133       one PPI::Document element, such a Policy would only be invoked once per
134       file.
135
136       Now comes the interesting part.  The "violates()" method does all the
137       work.  It is always called with 2 arguments: a reference to the current
138       PPI element that Perl::Critic is traversing, and a reference to the
139       entire PPI document. [And since this is an object method, there will be
140       an additional argument that is a reference to this object ($self), but
141       you already knew that!]
142
143         sub violates {
144             my ( $self, $elem, $doc ) = @_;
145
146       The violates() method then often performs some tests to make sure we
147       have the right "type" of element.  In our example, we know that the
148       element will be a PPI::Token::Word because that's what we declared back
149       in the "applies_to()" method.  However, we didn't specify exactly which
150       "word" we were looking for.  Evaluating a PPI element in a string con‐
151       text returns the literal form of the code.  So we make sure that this
152       PPI::Token::Word is, in fact, "grep".  If it's not, then we don't' need
153       to bother examining it.
154
155           return if $elem ne 'grep';
156
157       The "PPI::Token::Word" class is also used for barewords and methods
158       called on object references.  It is possible for someone to declare a
159       bareword hash key as "<%hash = ( grep =" 'foo' )>>.  We don't want to
160       test those types of elements because they don't represent function
161       calls to "grep".  So we use some handy utility functions from
162       Perl::Critic::Utils to make sure that this "grep" is actually in the
163       right context.
164
165           return if is_method_call($elem);
166           return if is_hash_key($elem);
167           return if is_subroutine_name($elem);
168
169       Now that we know this element is a call to the "grep" function, we can
170       look at the nearby elements to see what kind of arguments are being
171       passed to it.  Every PPI element is linked to its siblings, parent, and
172       children (if it has any).  Since those siblings could just be white‐
173       space, we use the "snext_sibling()" to get the next code-sibling (the
174       's' in "snext_sibling" stands for 'significant').
175
176           my $sib = $elem->snext_sibling() ⎪⎪ return;
177
178       In Perl, the parenthesis around argument lists are usually optional,
179       and PPI packs the elements into a PPI::Structure::List object when
180       parens are used.  So if the sibling is a PPI::Structure::List, we pull
181       out the first (significant) child of that list.  This child will be the
182       first argument to "grep".  If parens were not used, then the sibling
183       itself is the first argument.
184
185           my $arg = $sib->isa('PPI::Structure::List') ? $sib->schild(0) : $sib;
186
187       Finally, we now have a reference to the first argument to "grep".  If
188       that argument is a block (i.e. something in curly braces), then it will
189       be a PPI::Structure::Block, in which case our Policy is satisfied and
190       we just return nothing.
191
192           return if !$arg ⎪⎪ $arg->isa('PPI::Structure::Block');
193
194       But if it is not a PPI::Structure::Block, then we know that this call
195       to "grep" must be using the expression form, and that violates our Pol‐
196       icy.  So we create and return a new Perl::Critic::Violation object,
197       passing in the description, explanation, and severity of the violation,
198       as well as a reference to the PPI element that caused the violation.
199       And that's all there is to it!
200
201           my $sev = $self->get_severity();
202           return Perl::Critic::Violation->new( $desc, $expl, $elem, $sev );
203         }
204
205         1;
206
207       One last thing -- When you import Perl::Critic::Violation, it extracts
208       the DESCRIPTION section from the POD in your Policy module.  That text
209       can displayed in the diagnostic output when the Violations objects are
210       stringified.  So please include a DESCRIPTION section in the POD for
211       your Policy.  It should succinctly describe the behavior and motivation
212       for your Policy and include a few examples of both good and bad code.
213       Here's an example:
214
215         =pod
216
217         =head1 NAME
218
219         Perl::Critic::Policy::BuiltinFunctions::RequireBlockGrep
220
221         =head1 DESCRIPTION
222
223         The expression form of C<grep> and C<map> is awkward and hard to read.
224         Use the block forms instead.
225
226           @matches = grep   /pattern/,   @list;        #not ok
227           @matches = grep { /pattern/ }  @list;        #ok
228
229           @mapped = map   transform($_),   @list;      #not ok
230           @mapped = map { transform($_) }  @list;      #ok
231
232         =cut
233

AUTHOR

235       Jeffrey Ryan Thalhammer <thaljef@cpan.org>
236
238       Copyright (c) 2005-2007 Jeffrey Ryan Thalhammer.  All rights reserved.
239
240       This program is free software; you can redistribute it and/or modify it
241       under the same terms as Perl itself.  The full text of this license can
242       be found in the LICENSE file included with this module.
243
244
245
246perl v5.8.8                       2007-03-20        Perl::Critic::DEVELOPER(3)
Impressum