1 package Perl::Critic::Policy::DynamicMoose;
4 extends 'Perl::Critic::DynamicPolicy';
8 isa => 'PPI::Document',
9 handles => [qw/ppi_document/],
12 sub applies_to { 'PPI::Document' }
13 sub applies_to_metaclass { 'Class::MOP::Class', inner() }
14 sub default_themes { qw(moose dynamic), inner() }
16 around violation => sub {
24 my $doc = $self->ppi_document;
26 # Without this hack, Storable complains of being unable to reconstruct
27 # overloading for an unknown package (perhaps PPI::Document?). For some
28 # reason it works for PPI::Element. Anyway, this should hopefully be
29 # replaced with a more useful location, something like
30 # ( class:MyClass / attr:foo / builder:build_foo )
31 $element = $doc->find('PPI::Element')->[0];
34 return $self->$orig($desc, $expl, $element, @_);
37 sub violates_dynamic {
41 $self->document($doc);
43 my $old_packages = $self->_find_packages;
44 $self->_compile_document;
45 my @new_packages = $self->_new_packages($old_packages);
48 for my $package (@new_packages) {
49 my $meta = Class::MOP::class_of($package)
52 grep { $meta->isa($_) } $self->applies_to_metaclass
55 push @violations, $self->violates_metaclass($meta, $doc);
61 sub violates_metaclass { die "Your policy (" . blessed($_[0]) . ") needs to implement violates_metaclass" }
63 sub _compile_document {
65 my $doc = $self->document;
67 my $source_code = $doc->content;
71 die "Unable to execute " . $doc->filename . ": $@" if $@;
76 return [ Class::MOP::get_all_metaclass_names ];
85 $seen{$_} = 1 for @$old;
87 for (@{ $self->_find_packages }) {
88 push @new, $_ if !$seen{$_}++;
95 __PACKAGE__->meta->make_immutable;
103 Perl::Critic::Policy::DynamicMoose
107 This class is a base class for dynamic Moose policies. This class facilitates
108 critiquing metaclasses (instead of the usual PPI documents). For example, the
109 L<Perl::Critic::Policy::DynamicMoose::ProhibitPublicBuilders> policy critiques
110 metaclasses by checking whether any of their attributes' builders do not start
111 with an underscore. Due to the very dynamic nature of Moose and
112 metaprogramming, such policies will be much more effective than static analysis
113 at critiquing classes.
115 =head1 PUBLIC METHODS
119 =item C<applies_to_metaclass>
121 Returns a list of metaclass names that this policy can critique. By default,
122 the list is L<Class::MOP::Class>. You may use the augment modifier to add
123 other kinds of metaclasses, such as L<Moose::Meta::Role> without having to
124 repeat the L<Class::MOP::Class>:
126 augment applies_to_metaclass => sub { 'Moose::Meta::Role' };
128 Note that only the top-level metaclass is given to you. If you want to critique
129 only attributes, then you must do the Visiting yourself.
131 =item C<applies_to_themes>
133 Returns a list of themes for Perl::Critic so that users can run a particular
134 subset of themes on their code. By default, the list contains C<moose> and
135 C<dynamic>. You should use the augment modifier to add more themes instead
136 of overriding the method:
138 augment themes => sub { 'role' };
142 This extends the regular L<Perl::Critic::Policy/violation> method by providing
143 a (rather useless) default value for the C<element> parameter. For nearly all
144 cases, there's no easy way to find where a metaclass violation occurred. You
145 may still pass such an element if you have one. However, since you probably do
146 not, you should be exact in your violation's description.
148 =item C<violates_metaclass>
150 This method is required to be overridden by subclasses. It takes a metaclass
151 object and the L<Perl::Critic::Document> representing the entire compilation
152 unit. It is expected to return a list of L<Perl::Critic::Violation> objects.
158 The included policies are:
162 =item L<Perl::Critic::Policy::DynamicMoose::ProhibitPublicBuilders>
164 Prohibit public builder methods for attributes. [Severity: 3]
170 B<VERY IMPORTANT:> Most L<Perl::Critic> Policies (including all the ones that
171 ship with Perl::Critic> use pure static analysis -- they never compile nor
172 execute any of the code that they analyze. However, this policy is very
173 different. It actually attempts to compile your code and then compares the
174 subroutines mentioned in your code to those found in the symbol table.
175 Therefore you should B<not> use this Policy on any code that you do not trust,
176 or may have undesirable side-effects at compile-time (such as connecting to the
177 network or mutating files).
179 For this Policy to work, all the modules included in your code must be
180 installed locally, and must compile without error.
184 Shawn M Moore, C<sartak@bestpractical.com>