1 ##############################################################################
2 # $URL: http://perlcritic.tigris.org/svn/perlcritic/trunk/Perl-Critic/lib/Perl/Critic/PolicyParameter.pm $
3 # $Date: 2008-07-03 10:19:10 -0500 (Thu, 03 Jul 2008) $
6 ##############################################################################
8 package Perl::Critic::PolicyParameter;
17 Readonly::Array our @EXPORT_OK => qw{ $NO_DESCRIPTION_AVAILABLE };
19 use String::Format qw{ stringf };
21 use Perl::Critic::Exception::Fatal::PolicyDefinition
22 qw{ throw_policy_definition };
23 use Perl::Critic::PolicyParameter::Behavior;
24 use Perl::Critic::PolicyParameter::Behavior::Boolean;
25 use Perl::Critic::PolicyParameter::Behavior::Enumeration;
26 use Perl::Critic::PolicyParameter::Behavior::Integer;
27 use Perl::Critic::PolicyParameter::Behavior::String;
28 use Perl::Critic::PolicyParameter::Behavior::StringList;
30 use Perl::Critic::Utils qw{ :characters &interpolate };
31 use Perl::Critic::Utils::DataConversion qw{ &defined_or_empty };
33 our $VERSION = '1.088';
35 Readonly::Scalar our $NO_DESCRIPTION_AVAILABLE => 'No description available.';
37 #-----------------------------------------------------------------------------
39 # Grrr... one of the OO limitations of Perl: you can't put references to
40 # subclases in a superclass (well, not nicely). This map and method belong
42 Readonly::Hash my %BEHAVIORS =>
44 'boolean' => Perl::Critic::PolicyParameter::Behavior::Boolean->new(),
45 'enumeration' => Perl::Critic::PolicyParameter::Behavior::Enumeration->new(),
46 'integer' => Perl::Critic::PolicyParameter::Behavior::Integer->new(),
47 'string' => Perl::Critic::PolicyParameter::Behavior::String->new(),
48 'string list' => Perl::Critic::PolicyParameter::Behavior::StringList->new(),
51 sub _get_behavior_for_name {
52 my $behavior_name = shift;
54 my $behavior = $BEHAVIORS{$behavior_name}
55 or throw_policy_definition qq{There's no "$behavior_name" behavior.};
60 #-----------------------------------------------------------------------------
63 my ($class, $specification) = @_;
64 my $self = bless {}, $class;
66 defined $specification
67 or throw_policy_definition
68 'Attempt to create a ', __PACKAGE__, ' without a specification.';
70 my $behavior_specification;
72 my $specification_type = ref $specification;
73 if ( not $specification_type ) {
74 $self->{_name} = $specification;
76 $behavior_specification = {};
78 $specification_type eq 'HASH'
79 or throw_policy_definition
80 'Attempt to create a ',
82 " with a $specification_type as a specification.",
85 defined $specification->{name}
86 or throw_policy_definition
87 'Attempt to create a ', __PACKAGE__, ' without a name.';
88 $self->{_name} = $specification->{name};
90 $behavior_specification = $specification;
93 $self->_initialize_from_behavior($behavior_specification);
94 $self->_finish_standard_initialization($behavior_specification);
99 # See if the specification includes a Behavior name, and if so, let the
100 # Behavior with that name plug in its implementations of parser, etc.
101 sub _initialize_from_behavior {
102 my ($self, $specification) = @_;
104 my $behavior_name = $specification->{behavior};
106 if ($behavior_name) {
107 $behavior = _get_behavior_for_name($behavior_name);
109 $behavior = _get_behavior_for_name('string');
112 $self->{_behavior} = $behavior;
113 $self->{_behavior_values} = {};
115 $behavior->initialize_parameter($self, $specification);
120 # Grab the rest of the values out of the specification, including overrides
121 # of what the Behavior specified.
122 sub _finish_standard_initialization {
123 my ($self, $specification) = @_;
126 $specification->{description} || $NO_DESCRIPTION_AVAILABLE;
127 $self->_set_description($description);
128 $self->_set_default_string($specification->{default_string});
130 $self->_set_parser($specification->{parser});
135 #-----------------------------------------------------------------------------
140 return $self->{_name};
143 #-----------------------------------------------------------------------------
145 sub get_description {
148 return $self->{_description};
151 sub _set_description {
152 my ($self, $new_value) = @_;
154 return if not defined $new_value;
155 $self->{_description} = $new_value;
160 sub _get_description_with_trailing_period {
163 my $description = $self->get_description();
165 if ( $PERIOD ne substr $description, ( length $description ) - 1 ) {
166 $description .= $PERIOD;
169 $description = $EMPTY;
175 #-----------------------------------------------------------------------------
177 sub get_default_string {
180 return $self->{_default_string};
183 sub _set_default_string {
184 my ($self, $new_value) = @_;
186 return if not defined $new_value;
187 $self->{_default_string} = $new_value;
192 #-----------------------------------------------------------------------------
197 return $self->{_behavior};
200 sub _get_behavior_values {
203 return $self->{_behavior_values};
206 #-----------------------------------------------------------------------------
211 return $self->{_parser};
215 my ($self, $new_value) = @_;
217 return if not defined $new_value;
218 $self->{_parser} = $new_value;
223 #-----------------------------------------------------------------------------
225 sub parse_and_validate_config_value {
226 my ($self, $policy, $config) = @_;
228 my $config_string = $config->{$self->get_name()};
230 my $parser = $self->_get_parser();
232 $parser->($policy, $self, $config_string);
238 #-----------------------------------------------------------------------------
240 sub generate_full_description {
243 return $self->_get_behavior()->generate_parameter_description($self);
246 #-----------------------------------------------------------------------------
248 sub _generate_full_description {
249 my ($self, $prefix) = @_;
251 my $description = $self->generate_full_description();
253 if (not $description) {
258 $description =~ s/ ^ /$prefix/xmsg;
264 #-----------------------------------------------------------------------------
266 sub to_formatted_string {
267 my ($self, $format) = @_;
269 my %specification = (
270 n => sub { $self->get_name() },
271 d => sub { defined_or_empty( $self->get_description() ) },
272 D => sub { defined_or_empty( $self->get_default_string() ) },
273 f => sub { $self->_generate_full_description(@_) },
276 return stringf( interpolate($format), %specification );
279 #-----------------------------------------------------------------------------
285 #-----------------------------------------------------------------------------
289 =for stopwords parsable
293 Perl::Critic::PolicyParameter - Metadata about a parameter for a Policy.
298 A provider of validation and parsing of parameter values and metadata
308 Return the name of the parameter. This is the key that will be looked
309 for in the F<.perlcriticrc>.
312 =item C<get_description()>
314 Return an explanation of the significance of the parameter, as
315 provided by the developer of the policy.
318 =item C<get_default_string()>
320 Return a representation of the default value of this parameter as it
321 would appear if it was specified in a F<.perlcriticrc> file.
324 =item C<parse_and_validate_config_value( $parser, $config )>
326 Extract the configuration value for this parameter from the overall
327 configuration and initialize the policy based upon it.
330 =item C<generate_full_description()>
332 Produce a more complete explanation of the significance of this
333 parameter than the value returned by C<get_description()>.
335 If no description can be derived, returns the empty string.
337 Note that the result may contain multiple lines.
340 =item C<to_formatted_string( $format )>
342 Generate a string representation of this parameter, based upon the
345 The format is a combination of literal and escape characters similar
346 to the way C<sprintf> works. If you want to know the specific
347 formatting capabilities, look at L<String::Format>. Valid escape
354 The name of the parameter.
358 The description, as supplied by the programmer.
362 The default value, in a parsable form.
366 The full description, which is an extension of the value returned by
367 C<%d>. Takes a parameter of a prefix for the beginning of each line.
378 L<Perl::Critic::DEVELOPER/"MAKING YOUR POLICY CONFIGURABLE">
383 Elliot Shank <perl@galumph.com>
387 Copyright (c) 2006-2008 Elliot Shank. All rights reserved.
389 This program is free software; you can redistribute it and/or modify
390 it under the same terms as Perl itself. The full text of this license
391 can be found in the LICENSE file included with this module.
397 # cperl-indent-level: 4
399 # indent-tabs-mode: nil
400 # c-indentation-style: bsd
402 # ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :