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