File Coverage

blib/lib/Moose/Role.pm
Criterion Covered Total %
statement 93 94 98.9
branch 31 34 91.1
condition 4 5 80.0
subroutine 26 26 100.0
pod 2 13 15.3
total 156 172 90.7


line stmt bran cond sub pod time code
1 269     269   5096642 use strict;
  269         2013  
  269         9830  
2 269     269   1662 use warnings;
  269         1113  
  269         14771  
3             package Moose::Role;
4             our $VERSION = '2.2205';
5              
6 269     269   1942 use Scalar::Util ();
  269         1054  
  269         4455  
7 269     269   1536 use Carp ();
  269         1073  
  269         6230  
8 269     269   38715 use Class::Load 'is_class_loaded';
  269         1358971  
  269         20015  
9 269     269   2699 use Module::Runtime 'module_notional_filename';
  269         642  
  269         2950  
10              
11 269     269   65217 use Sub::Exporter;
  269         291383  
  269         3043  
12              
13 269     269   122875 use Moose ();
  269         1267  
  269         9311  
14 269     269   2759 use Moose::Util 'throw_exception';
  269         718  
  269         3458  
15              
16 269     269   87274 use Moose::Exporter;
  269         755  
  269         3969  
17 269     269   1898 use Moose::Meta::Role;
  269         771  
  269         9135  
18 269     269   2336 use Moose::Util::TypeConstraints;
  269         1295  
  269         3954  
19              
20             sub extends {
21 2     2 0 418 throw_exception("RolesDoNotSupportExtends");
22             }
23              
24             sub with {
25 508     508 0 2455 Moose::Util::apply_all_roles( shift, @_ );
26             }
27              
28             sub requires {
29 165     165 1 535 my $meta = shift;
30 165 100       694 throw_exception( MustSpecifyAtleastOneMethod => role_name => $meta->name ) unless @_;
31 164         954 $meta->add_required_methods(@_);
32             }
33              
34             sub excludes {
35 9     9 1 28 my $meta = shift;
36 9 100       49 throw_exception( MustSpecifyAtleastOneRole => role_name => $meta->name ) unless @_;
37 8         60 $meta->add_excluded_roles(@_);
38             }
39              
40             sub has {
41 432     432 0 1252 my $meta = shift;
42 432         966 my $name = shift;
43 432 100       1701 throw_exception( InvalidHasProvidedInARole => role_name => $meta->name,
44             attribute_name => $name,
45             )
46             if @_ == 1;
47 431         1913 my %context = Moose::Util::_caller_info;
48 431         1635 $context{context} = 'has declaration';
49 431         1112 $context{type} = 'role';
50 431         2338 my %options = ( definition_context => \%context, @_ );
51 431 100       1913 my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ];
52 431         3491 $meta->add_attribute( $_, %options ) for @$attrs;
53             }
54              
55             sub _add_method_modifier {
56 393     393   843 my $type = shift;
57 393         703 my $meta = shift;
58              
59 393 100       1227 if ( ref($_[0]) eq 'Regexp' ) {
60 5         45 throw_exception( RolesDoNotSupportRegexReferencesForMethodModifiers => modifier_type => $type,
61             role_name => $meta->name,
62             );
63             }
64              
65 388         1844 Moose::Util::add_method_modifier($meta, $type, \@_);
66             }
67              
68 105     105 0 431 sub before { _add_method_modifier('before', @_) }
69              
70 34     34 0 148 sub after { _add_method_modifier('after', @_) }
71              
72 254     254 0 1235 sub around { _add_method_modifier('around', @_) }
73              
74             # see Moose.pm for discussion
75             sub super {
76 2241 50   2241 0 5694 return unless $Moose::SUPER_BODY;
77 2241         5455 $Moose::SUPER_BODY->(@Moose::SUPER_ARGS);
78             }
79              
80             sub override {
81 167     167 0 383 my $meta = shift;
82 167         445 my ( $name, $code ) = @_;
83 167         659 $meta->add_override_method_modifier( $name, $code );
84             }
85              
86             sub inner {
87 2     2 0 158 throw_exception("RolesDoNotSupportInner");
88             }
89              
90             sub augment {
91 2     2 0 146 throw_exception("RolesDoNotSupportAugment");
92             }
93              
94             Moose::Exporter->setup_import_methods(
95             with_meta => [
96             qw( with requires excludes has before after around override )
97             ],
98             as_is => [
99             qw( extends super inner augment ),
100             'Carp::confess',
101             'Scalar::Util::blessed',
102             ],
103             );
104              
105             sub init_meta {
106 1316     1316 0 3252 shift;
107 1316         6256 my %args = @_;
108              
109 1316         3258 my $role = $args{for_class};
110              
111 1316 100       3975 unless ($role) {
112 1         8 require Moose;
113 1         7 throw_exception( InitMetaRequiresClass => params => \%args );
114             }
115              
116 1315   100     6537 my $metaclass = $args{metaclass} || "Moose::Meta::Role";
117 1315 100       5431 my $meta_name = exists $args{meta_name} ? $args{meta_name} : 'meta';
118              
119 1315 100       8941 throw_exception( MetaclassNotLoaded => class_name => $metaclass )
120             unless is_class_loaded($metaclass);
121              
122 1314 100       10267 throw_exception( MetaclassMustBeASubclassOfMooseMetaRole => role_name => $metaclass )
123             unless $metaclass->isa('Moose::Meta::Role');
124              
125             # make a subtype for each Moose role
126 1313 100       6159 role_type $role unless find_type_constraint($role);
127              
128 1313         3405 my $meta;
129 1313 100       6123 if ( $meta = Class::MOP::get_metaclass_by_name($role) ) {
130 25 100       127 unless ( $meta->isa("Moose::Meta::Role") ) {
131 2 100       9 if ( $meta->isa('Moose::Meta::Class') ) {
132 1         5 throw_exception( MetaclassIsAClassNotASubclassOfGivenMetaclass => class_name => $role,
133             metaclass => $metaclass,
134             );
135             } else {
136 1         5 throw_exception( MetaclassIsNotASubclassOfGivenMetaclass => class_name => $role,
137             metaclass => $metaclass,
138             );
139             }
140             }
141             }
142             else {
143 1288         8126 $meta = $metaclass->initialize($role);
144 1288         9497 my $filename = module_notional_filename($meta->name);
145             $INC{$filename} = '(set by Moose)'
146 1288 100       39159 unless exists $INC{$filename};
147             }
148              
149 1311 50       4362 if (defined $meta_name) {
150             # also check for inherited non moose 'meta' method?
151 1311         6772 my $existing = $meta->get_method($meta_name);
152 1311 50 66     5201 if ($existing && !$existing->isa('Class::MOP::Method::Meta')) {
153 0         0 Carp::cluck "Moose::Role is overwriting an existing method named "
154             . "$meta_name in role $role with a method "
155             . "which returns the class's metaclass. If this is "
156             . "actually what you want, you should remove the "
157             . "existing method, otherwise, you should rename or "
158             . "disable this generated method using the "
159             . "'-meta_name' option to 'use Moose::Role'.";
160             }
161 1311         6206 $meta->_add_meta_method($meta_name);
162             }
163              
164 1311         5818 return $meta;
165             }
166              
167             1;
168              
169             # ABSTRACT: The Moose Role
170              
171             __END__
172              
173             =pod
174              
175             =encoding UTF-8
176              
177             =head1 NAME
178              
179             Moose::Role - The Moose Role
180              
181             =head1 VERSION
182              
183             version 2.2205
184              
185             =head1 SYNOPSIS
186              
187             package Eq;
188             use Moose::Role; # automatically turns on strict and warnings
189              
190             requires 'equal';
191              
192             sub no_equal {
193             my ($self, $other) = @_;
194             !$self->equal($other);
195             }
196              
197             # ... then in your classes
198              
199             package Currency;
200             use Moose; # automatically turns on strict and warnings
201              
202             with 'Eq';
203              
204             sub equal {
205             my ($self, $other) = @_;
206             $self->as_float == $other->as_float;
207             }
208              
209             # ... and also
210              
211             package Comparator;
212             use Moose;
213              
214             has compare_to => (
215             is => 'ro',
216             does => 'Eq',
217             handles => 'Eq',
218             );
219              
220             # ... which allows
221              
222             my $currency1 = Currency->new(...);
223             my $currency2 = Currency->new(...);
224             Comparator->new(compare_to => $currency1)->equal($currency2);
225              
226             =head1 DESCRIPTION
227              
228             The concept of roles is documented in L<Moose::Manual::Roles>. This document
229             serves as API documentation.
230              
231             =head1 EXPORTED FUNCTIONS
232              
233             Moose::Role currently supports all of the functions that L<Moose> exports, but
234             differs slightly in how some items are handled (see L</CAVEATS> below for
235             details).
236              
237             Moose::Role also offers two role-specific keyword exports:
238              
239             =head2 requires (@method_names)
240              
241             Roles can require that certain methods are implemented by any class which
242             C<does> the role.
243              
244             Note that attribute accessors also count as methods for the purposes
245             of satisfying the requirements of a role.
246              
247             =head2 excludes (@role_names)
248              
249             Roles can C<exclude> other roles, in effect saying "I can never be combined
250             with these C<@role_names>". This is a feature which should not be used
251             lightly.
252              
253             =head2 no Moose::Role
254              
255             Moose::Role offers a way to remove the keywords it exports, through the
256             C<unimport> method. You simply have to say C<no Moose::Role> at the bottom of
257             your code for this to work.
258              
259             =head1 METACLASS
260              
261             When you use Moose::Role, you can specify traits which will be applied to your
262             role metaclass:
263              
264             use Moose::Role -traits => 'My::Trait';
265              
266             This is very similar to the attribute traits feature. When you do
267             this, your class's C<meta> object will have the specified traits
268             applied to it. See L<Moose/Metaclass and Trait Name Resolution> for more
269             details.
270              
271             All role metaclasses (note, not the role itself) extend L<Moose::Meta::Role>.
272             You can test if a package is a role or not using L<Moose::Util/is_role>.
273              
274             =head1 APPLYING ROLES
275              
276             In addition to being applied to a class using the 'with' syntax (see
277             L<Moose::Manual::Roles>) and using the L<Moose::Util> 'apply_all_roles'
278             method, roles may also be applied to an instance of a class using
279             L<Moose::Util> 'apply_all_roles' or the role's metaclass:
280              
281             MyApp::Test::SomeRole->meta->apply( $instance );
282              
283             Doing this creates a new, mutable, anonymous subclass, applies the role to that,
284             and reblesses. In a debugger, for example, you will see class names of the
285             form C< Moose::Meta::Class::__ANON__::SERIAL::6 >, which means that doing a
286             'ref' on your instance may not return what you expect. See L<Moose::Object> for
287             'DOES'.
288              
289             Additional params may be added to the new instance by providing
290             'rebless_params'. See L<Moose::Meta::Role::Application::ToInstance>.
291              
292             =head1 CAVEATS
293              
294             Role support has only a few caveats:
295              
296             =over 4
297              
298             =item *
299              
300             Roles cannot use the C<extends> keyword; it will throw an exception for now.
301             The same is true of the C<augment> and C<inner> keywords (not sure those
302             really make sense for roles). All other Moose keywords will be I<deferred>
303             so that they can be applied to the consuming class.
304              
305             =item *
306              
307             Role composition does its best to B<not> be order-sensitive when it comes to
308             conflict resolution and requirements detection. However, it is order-sensitive
309             when it comes to method modifiers. All before/around/after modifiers are
310             included whenever a role is composed into a class, and then applied in the order
311             in which the roles are used. This also means that there is no conflict for
312             before/around/after modifiers.
313              
314             In most cases, this will be a non-issue; however, it is something to keep in
315             mind when using method modifiers in a role. You should never assume any
316             ordering.
317              
318             =back
319              
320             =head1 BUGS
321              
322             See L<Moose/BUGS> for details on reporting bugs.
323              
324             =head1 AUTHORS
325              
326             =over 4
327              
328             =item *
329              
330             Stevan Little <stevan@cpan.org>
331              
332             =item *
333              
334             Dave Rolsky <autarch@urth.org>
335              
336             =item *
337              
338             Jesse Luehrs <doy@cpan.org>
339              
340             =item *
341              
342             Shawn M Moore <sartak@cpan.org>
343              
344             =item *
345              
346             יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
347              
348             =item *
349              
350             Karen Etheridge <ether@cpan.org>
351              
352             =item *
353              
354             Florian Ragwitz <rafl@debian.org>
355              
356             =item *
357              
358             Hans Dieter Pearcey <hdp@cpan.org>
359              
360             =item *
361              
362             Chris Prather <chris@prather.org>
363              
364             =item *
365              
366             Matt S Trout <mstrout@cpan.org>
367              
368             =back
369              
370             =head1 COPYRIGHT AND LICENSE
371              
372             This software is copyright (c) 2006 by Infinity Interactive, Inc.
373              
374             This is free software; you can redistribute it and/or modify it under
375             the same terms as the Perl 5 programming language system itself.
376              
377             =cut