Commit | Line | Data |
84a1bb62 |
1 | package Perl::Critic::Policy::DynamicMoose; |
a3c86d00 |
2 | use Moose; |
8f31d0d0 |
3 | use MooseX::NonMoose; |
a3c86d00 |
4 | extends 'Perl::Critic::DynamicPolicy'; |
5 | |
8f31d0d0 |
6 | has document => ( |
1e6decf8 |
7 | is => 'rw', |
8 | isa => 'PPI::Document', |
9 | handles => [qw/ppi_document/], |
8f31d0d0 |
10 | ); |
11 | |
cc784ef4 |
12 | sub applies_to { 'PPI::Document' } |
914f300c |
13 | sub applies_to_metaclass { 'Class::MOP::Class', inner() } |
8f31d0d0 |
14 | |
15 | around violation => sub { |
1e6decf8 |
16 | my $orig = shift; |
17 | my $self = shift; |
18 | my $desc = shift; |
19 | my $expl = shift; |
20 | my $element = shift; |
21 | |
22 | if (!$element) { |
23 | my $doc = $self->ppi_document; |
24 | $element = $doc->find('PPI::Element')->[0]; |
25 | } |
8f31d0d0 |
26 | |
1e6decf8 |
27 | return $self->$orig($desc, $expl, $element, @_); |
8f31d0d0 |
28 | }; |
29 | |
a3c86d00 |
30 | sub violates_dynamic { |
31 | my $self = shift; |
32 | my $doc = shift; |
33 | |
8f31d0d0 |
34 | $self->document($doc); |
8f31d0d0 |
35 | |
34502164 |
36 | my $old_packages = $self->find_packages; |
37 | $self->compile_document; |
38 | my @new_packages = $self->new_packages($old_packages); |
8f31d0d0 |
39 | |
40 | my @violations; |
34502164 |
41 | for my $package (@new_packages) { |
c140dc59 |
42 | my $meta = Class::MOP::class_of($package) |
43 | or next; |
44 | |
45 | grep { $meta->isa($_) } $self->applies_to_metaclass |
46 | or next; |
8f31d0d0 |
47 | |
48 | push @violations, $self->violates_metaclass($meta, $doc); |
49 | } |
50 | |
51 | return @violations; |
52 | } |
53 | |
54 | sub compile_document { |
55 | my $self = shift; |
56 | my $doc = $self->document; |
57 | |
1ad52929 |
58 | my $source_code = $doc->content; |
59 | |
60 | eval $source_code; |
61 | |
62 | die "Unable to execute " . $doc->filename . ": $@" if $@; |
8f31d0d0 |
63 | } |
64 | |
65 | sub find_packages { |
66 | my $self = shift; |
34502164 |
67 | return [ Class::MOP::get_all_metaclass_names ]; |
68 | } |
69 | |
70 | sub new_packages { |
71 | my $self = shift; |
72 | my $old = shift; |
73 | my @new; |
74 | my %seen; |
75 | |
76 | $seen{$_} = 1 for @$old; |
77 | |
78 | for (@{ $self->find_packages }) { |
79 | push @new, $_ if !$seen{$_}++; |
80 | } |
a3c86d00 |
81 | |
34502164 |
82 | return @new; |
a3c86d00 |
83 | } |
84 | |
a3c86d00 |
85 | no Moose; |
86 | |
87 | 1; |
88 | |