Handle overriding and wrapping in the same class
[gitmo/Perl-Critic-Dynamic-Moose.git] / lib / Perl / Critic / Policy / DynamicMoose / RequireMethodModifiers.pm
1 package Perl::Critic::Policy::DynamicMoose::RequireMethodModifiers;
2 use Moose;
3 extends 'Perl::Critic::Policy::DynamicMoose';
4
5 use Perl::Critic::Utils ':severities';
6 use Perl::Critic::Utils::Moose 'meta_type';
7
8 Readonly::Scalar my $EXPL => q{Method modifiers make it clear that you're overriding methods.};
9 sub default_severity { $SEVERITY_LOW }
10
11 sub violates_metaclass {
12     my $self = shift;
13     my $meta = shift;
14
15     my @violations;
16
17     my $map = $meta->get_method_map;
18
19     for my $name (keys %$map) {
20         my $method = $map->{$name};
21
22         # override and augment modifiers are always fine.
23         next if $method->isa('Moose::Meta::Method::Overridden')
24              || $method->isa('Moose::Meta::Method::Augmented');
25
26         # Since we can implicitly override and wrap in the same class, we
27         # need to be a little more careful here.
28         if ($method->isa('Class::MOP::Method::Wrapped')) {
29             my $orig_method = $method->get_original_method;
30             next if $method->associated_metaclass->name
31                  ne $orig_method->associated_metaclass->name;
32         }
33
34         # Generated methods
35         next if $method->isa('Class::MOP::Method::Generated');
36
37         # XXX: this freaking sucks
38         next if $name eq 'meta' || $name eq 'BUILD' || $name eq 'DEMOLISH';
39
40         my $next = $meta->find_next_method_by_name($name);
41
42         # Adding new methods is always fine.
43         next if !$next;
44
45         push @violations, $self->violation("The '$name' method of class " . $meta->name . " does not use a method modifier to override its superclass implementation.", $EXPL);
46     }
47
48     return @violations;
49 }
50
51 no Moose;
52
53 1;
54
55 __END__
56
57 =head1 NAME
58
59 Perl::Critic::Policy::DynamicMoose::RequireMethodModifiers
60
61 =head1 DESCRIPTION
62
63
64 =head1 WARNING
65
66 B<VERY IMPORTANT:> Most L<Perl::Critic> Policies (including all the ones that
67 ship with Perl::Critic> use pure static analysis -- they never compile nor
68 execute any of the code that they analyze.  However, this policy is very
69 different.  It actually attempts to compile your code and then compares the
70 subroutines mentioned in your code to those found in the symbol table.
71 Therefore you should B<not> use this Policy on any code that you do not trust,
72 or may have undesirable side-effects at compile-time (such as connecting to the
73 network or mutating files).
74
75 For this Policy to work, all the modules included in your code must be
76 installed locally, and must compile without error.
77
78 =head1 AUTHOR
79
80 Shawn M Moore, C<sartak@bestpractical.com>
81
82 =cut
83