Make method generators extensible
[gitmo/Mouse.git] / lib / Mouse / Role.pm
1 package Mouse::Role;
2 use Mouse::Exporter; # enables strict and warnings
3
4 our $VERSION = '0.40';
5
6 use Carp         qw(confess);
7 use Scalar::Util qw(blessed);
8
9 use Mouse::Util  qw(not_supported);
10
11 use Mouse ();
12
13 Mouse::Exporter->setup_import_methods(
14     as_is => [qw(
15         extends with
16         has
17         before after around
18         override super
19         augment  inner
20
21         requires excludes
22     ),
23         \&Scalar::Util::blessed,
24         \&Carp::confess,
25     ],
26 );
27
28 # XXX: for backward compatibility
29 our @EXPORT = qw(
30     extends with
31     has
32     before after around
33     override super
34     augment  inner
35
36     requires excludes
37
38     blessed confess
39 );
40
41 sub before {
42     my $meta = Mouse::Meta::Role->initialize(scalar caller);
43
44     my $code = pop;
45     for (@_) {
46         $meta->add_before_method_modifier($_ => $code);
47     }
48 }
49
50 sub after {
51     my $meta = Mouse::Meta::Role->initialize(scalar caller);
52
53     my $code = pop;
54     for (@_) {
55         $meta->add_after_method_modifier($_ => $code);
56     }
57 }
58
59 sub around {
60     my $meta = Mouse::Meta::Role->initialize(scalar caller);
61
62     my $code = pop;
63     for (@_) {
64         $meta->add_around_method_modifier($_ => $code);
65     }
66 }
67
68
69 sub super {
70     return if !defined $Mouse::SUPER_BODY;
71     $Mouse::SUPER_BODY->(@Mouse::SUPER_ARGS);
72 }
73
74 sub override {
75     # my($name, $code) = @_;
76     Mouse::Meta::Role->initialize(scalar caller)->add_override_method_modifier(@_);
77 }
78
79 # We keep the same errors messages as Moose::Role emits, here.
80 sub inner {
81     Carp::croak "Roles cannot support 'inner'";
82 }
83
84 sub augment {
85     Carp::croak "Roles cannot support 'augment'";
86 }
87
88 sub has {
89     my $meta = Mouse::Meta::Role->initialize(scalar caller);
90     my $name = shift;
91
92     $meta->add_attribute($_ => @_) for ref($name) ? @{$name} : $name;
93 }
94
95 sub extends  {
96     Carp::croak "Roles do not support 'extends'"
97 }
98
99 sub with     {
100     my $meta = Mouse::Meta::Role->initialize(scalar caller);
101     Mouse::Util::apply_all_roles($meta->name, @_);
102 }
103
104 sub requires {
105     my $meta = Mouse::Meta::Role->initialize(scalar caller);
106     $meta->throw_error("Must specify at least one method") unless @_;
107     $meta->add_required_methods(@_);
108 }
109
110 sub excludes {
111     not_supported;
112 }
113
114 sub init_meta{
115     shift;
116     my %args = @_;
117
118     my $class = $args{for_class}
119         or Carp::confess("Cannot call init_meta without specifying a for_class");
120
121     my $metaclass  = $args{metaclass}  || 'Mouse::Meta::Role';
122
123     my $meta = $metaclass->initialize($class);
124
125     $meta->add_method(meta => sub{
126         $metaclass->initialize(ref($_[0]) || $_[0]);
127     });
128
129     # make a role type for each Mouse role
130     Mouse::Util::TypeConstraints::role_type($class)
131         unless Mouse::Util::TypeConstraints::find_type_constraint($class);
132
133     return $meta;
134 }
135
136 1;
137
138 __END__
139
140 =head1 NAME
141
142 Mouse::Role - The Mouse Role
143
144 =head1 VERSION
145
146 This document describes Mouse version 0.40
147
148 =head1 SYNOPSIS
149
150     package MyRole;
151     use Mouse::Role;
152
153 =head1 KEYWORDS
154
155 =head2 C<< meta -> Mouse::Meta::Role >>
156
157 Returns this role's metaclass instance.
158
159 =head2 C<< before (method|methods) -> CodeRef >>
160
161 Sets up a B<before> method modifier. See L<Moose/before> or
162 L<Class::Method::Modifiers/before>.
163
164 =head2 C<< after (method|methods) => CodeRef >>
165
166 Sets up an B<after> method modifier. See L<Moose/after> or
167 L<Class::Method::Modifiers/after>.
168
169 =head2 C<< around (method|methods) => CodeRef >>
170
171 Sets up an B<around> method modifier. See L<Moose/around> or
172 L<Class::Method::Modifiers/around>.
173
174 =head2 C<super>
175
176 Sets up the B<super> keyword. See L<Moose/super>.
177
178 =head2  C<< override method => CodeRef >>
179
180 Sets up an B<override> method modifier. See L<Moose/Role/override>.
181
182 =head2 C<inner>
183
184 This is not supported in roles and emits an error. See L<Moose/Role>.
185
186 =head2 C<< augment method => CodeRef >>
187
188 This is not supported in roles and emits an error. See L<Moose/Role>.
189
190 =head2 C<< has (name|names) => parameters >>
191
192 Sets up an attribute (or if passed an arrayref of names, multiple attributes) to
193 this role. See L<Mouse/has>.
194
195 =head2 C<< confess(error) -> BOOM >>
196
197 L<Carp/confess> for your convenience.
198
199 =head2 C<< blessed(value) -> ClassName | undef >>
200
201 L<Scalar::Util/blessed> for your convenience.
202
203 =head1 MISC
204
205 =head2 import
206
207 Importing Mouse::Role will give you sugar.
208
209 =head2 unimport
210
211 Please unimport (C<< no Mouse::Role >>) so that if someone calls one of the
212 keywords (such as L</has>) it will break loudly instead breaking subtly.
213
214 =head1 SEE ALSO
215
216 L<Moose::Role>
217
218 =cut
219