Login
Self-compliance with ProhibitUnrestrictedNoCritic
[gknop/Perl-Critic.git] / lib / Perl / Critic / Policy / Modules / RequireVersionVar.pm
CommitLineData
6036a254 1##############################################################################
dff08b70
JRT
2# $URL$
3# $Date$
4# $Author$
5# $Revision$
6036a254 6##############################################################################
dff08b70 7
59b05e08
JRT
8package Perl::Critic::Policy::Modules::RequireVersionVar;
9
df6dee2b 10use 5.006001;
59b05e08
JRT
11use strict;
12use warnings;
c680a9c9
ES
13use Readonly;
14
59b05e08 15use List::MoreUtils qw(any);
c680a9c9
ES
16
17use Perl::Critic::Utils qw{ :severities };
59b05e08
JRT
18use base 'Perl::Critic::Policy';
19
173667ce 20our $VERSION = '1.093_01';
59b05e08 21
6036a254 22#-----------------------------------------------------------------------------
dff08b70 23
c0631e45 24Readonly::Scalar my $DESC => q{No "$VERSION" variable found}; ## no critic (RequireInterpolation)
c680a9c9 25Readonly::Scalar my $EXPL => [ 404 ];
59b05e08 26
6036a254 27#-----------------------------------------------------------------------------
59b05e08 28
c680a9c9 29sub supported_parameters { return () }
bc46743d
JRT
30sub default_severity { return $SEVERITY_LOW }
31sub default_themes { return qw(core pbp readability) }
32sub applies_to { return 'PPI::Document' }
dff08b70 33
6036a254 34#-----------------------------------------------------------------------------
bf159007 35
59b05e08
JRT
36sub violates {
37 my ( $self, $elem, $doc ) = @_;
59b05e08 38
bc46743d 39 return if $doc->find_first( \&_is_VERSION_declaration );
dff08b70 40
59b05e08 41 #If we get here, then no $VERSION was found
c680a9c9 42 return $self->violation( $DESC, $EXPL, $doc );
59b05e08
JRT
43}
44
bc46743d
JRT
45#-----------------------------------------------------------------------------
46
c0631e45 47sub _is_VERSION_declaration { ## no critic (ArgUnpacking)
bc46743d
JRT
48 return 1 if _is_our_VERSION(@_);
49 return 1 if _is_vars_VERSION(@_);
50 return 1 if _is_package_VERSION(@_);
51 return 1 if _is_readonly_VERSION(@_);
52 return 0;
59b05e08
JRT
53}
54
bc46743d 55#-----------------------------------------------------------------------------
dff08b70 56
bc46743d 57sub _is_our_VERSION {
e5f6c18d 58 my (undef, $elem) = @_;
59b05e08
JRT
59 $elem->isa('PPI::Statement::Variable') || return 0;
60 $elem->type() eq 'our' || return 0;
c0631e45 61 return any { $_ eq '$VERSION' } $elem->variables(); ## no critic (RequireInterpolation)
59b05e08
JRT
62}
63
bc46743d 64#-----------------------------------------------------------------------------
dff08b70 65
bc46743d 66sub _is_vars_VERSION {
e5f6c18d 67 my (undef, $elem) = @_;
59b05e08
JRT
68 $elem->isa('PPI::Statement::Include') || return 0;
69 $elem->pragma() eq 'vars' || return 0;
a0dcf06f 70 return $elem =~ m{ \$VERSION }xms; #Crude, but usually works
59b05e08
JRT
71}
72
bc46743d 73#-----------------------------------------------------------------------------
dff08b70 74
bc46743d 75sub _is_package_VERSION {
e5f6c18d 76 my (undef, $elem) = @_;
59b05e08 77 $elem->isa('PPI::Token::Symbol') || return 0;
a0dcf06f 78 return $elem =~ m{ \A \$ \S+ ::VERSION \z }xms;
59b05e08
JRT
79 #TODO: ensure that it is in _this_ package!
80}
dff08b70 81
bc46743d
JRT
82#-----------------------------------------------------------------------------
83
84sub _is_readonly_VERSION {
85
86 #---------------------------------------------------------------
87 # Readonly VERSION statements usually come in one of two forms:
88 #
89 # Readonly our $VERSION = 1.0;
90 # Readonly::Scalar our $VERSION = 1.0;
91 #---------------------------------------------------------------
92
93 my (undef, $elem) = @_;
94 $elem->isa('PPI::Token::Symbol') || return 0;
a0dcf06f 95 return 0 if $elem !~ m{ \A \$VERSION \z }xms;
bc46743d
JRT
96
97 my $psib = $elem->sprevious_sibling() || return 0;
98 return 0 if $psib ne 'our';
99
100 my $ppsib = $psib->sprevious_sibling() || return 0;
101 return $ppsib eq 'Readonly' || $ppsib eq 'Readonly::Scalar';
102}
103
59b05e08
JRT
1041;
105
106__END__
107
6036a254 108#-----------------------------------------------------------------------------
dff08b70 109
59b05e08
JRT
110=pod
111
112=head1 NAME
113
f017d93a 114Perl::Critic::Policy::Modules::RequireVersionVar - Give every module a C<$VERSION> number.
59b05e08 115
11f53956 116
af93c316
ES
117=head1 AFFILIATION
118
11f53956
ES
119This Policy is part of the core L<Perl::Critic|Perl::Critic>
120distribution.
af93c316
ES
121
122
59b05e08
JRT
123=head1 DESCRIPTION
124
40b4a6ae 125Every Perl file (modules, libraries, and programs) should have a
59b05e08
JRT
126C<$VERSION> variable. The C<$VERSION> allows clients to insist on a
127particular revision of your file like this:
128
11f53956 129 use SomeModule 2.4; #Only loads version 2.4
59b05e08
JRT
130
131This Policy scans your file for any package variable named
132C<$VERSION>. I'm assuming that you are using C<strict>, so you'll
133have to declare it like one of these:
134
11f53956
ES
135 our $VERSION = 1.0611;
136 $MyPackage::VERSION = 1.061;
137 use vars qw($VERSION);
a0dcf06f 138 use version; our $VERSION = qv(1.0611);
86bf4aa6 139
11f53956
ES
140A common practice is to use the C<$Revision$> keyword to
141automatically define the C<$VERSION> variable like this:
59b05e08 142
11f53956 143 our ($VERSION) = '$Revision$' =~ m{ \$Revision: \s+ (\S+) }x;
59b05e08 144
0cb729f0
ES
145
146=head1 CONFIGURATION
147
49860482 148This Policy is not configurable except for the standard options.
0cb729f0
ES
149
150
86bf4aa6 151=head1 NOTES
59b05e08
JRT
152
153Conway recommends using the C<version> pragma instead of raw numbers
154or 'v-strings.' However, this Policy only insists that the
155C<$VERSION> be defined somehow. I may try to extend this in the
156future.
157
11f53956 158
59b05e08
JRT
159=head1 AUTHOR
160
161Jeffrey Ryan Thalhammer <thaljef@cpan.org>
162
11f53956 163
59b05e08
JRT
164=head1 COPYRIGHT
165
20dfddeb 166Copyright (c) 2005-2008 Jeffrey Ryan Thalhammer. All rights reserved.
59b05e08
JRT
167
168This program is free software; you can redistribute it and/or modify
169it under the same terms as Perl itself. The full text of this license
170can be found in the LICENSE file included with this module.
171
172=cut
737d3b65
CD
173
174# Local Variables:
175# mode: cperl
176# cperl-indent-level: 4
177# fill-column: 78
178# indent-tabs-mode: nil
179# c-indentation-style: bsd
180# End:
96fed375 181# ex: set ts=8 sts=4 sw=4 tw=78 ft=perl expandtab shiftround :