729094b838c26633b05fafb5627b343fcb8546c4
[gitmo/Perl-Critic-Dynamic-Moose.git] / lib / Perl / Critic / Policy / DynamicMoose.pm
1 package Perl::Critic::Policy::DynamicMoose;
2 use Moose;
3 use MooseX::NonMoose;
4 extends 'Perl::Critic::DynamicPolicy';
5
6 has document => (
7     is      => 'rw',
8     isa     => 'PPI::Document',
9     handles => [qw/ppi_document/],
10 );
11
12 sub applies_to { 'PPI::Document' }
13 sub applies_to_metaclass { 'Class::MOP::Class', inner() }
14
15 around violation => sub {
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     }
26
27     return $self->$orig($desc, $expl, $element, @_);
28 };
29
30 sub violates_dynamic {
31     my $self = shift;
32     my $doc  = shift;
33
34     $self->document($doc);
35
36     my $old_packages = $self->find_packages;
37     $self->compile_document;
38     my @new_packages = $self->new_packages($old_packages);
39
40     my @violations;
41     for my $package (@new_packages) {
42         my $meta = Class::MOP::class_of($package)
43             or next;
44
45         grep { $meta->isa($_) } $self->applies_to_metaclass
46             or next;
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
58     my $source_code = $doc->content;
59
60     eval $source_code;
61
62     die "Unable to execute " . $doc->filename . ": $@" if $@;
63 }
64
65 sub find_packages {
66     my $self = shift;
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     }
81
82     return @new;
83 }
84
85 no Moose;
86
87 1;
88