—package
Moose::Meta::Role;
our
$VERSION
=
'2.2207'
;
use
strict;
use
warnings;
use
metaclass;
use
Moose::Meta::Class;
'Class::MOP::Mixin::HasAttributes'
,
'Class::MOP::Mixin::HasMethods'
,
'Class::MOP::Mixin::HasOverloads'
;
Class::MOP::MiniTrait::apply(__PACKAGE__,
'Moose::Meta::Object::Trait'
);
## ------------------------------------------------------------------
## NOTE:
## I normally don't do this, but I am doing
## a whole bunch of meta-programmin' in this
## module, so it just makes sense. For a clearer
## picture of what is going on in the next
## several lines of code, look at the really
## big comment at the end of this file (right
## before the POD).
## - SL
## ------------------------------------------------------------------
my
$META
= __PACKAGE__->meta;
## ------------------------------------------------------------------
## attributes ...
# NOTE:
# since roles are lazy, we hold all the attributes
# of the individual role in 'stasis' until which
# time when it is applied to a class. This means
# keeping a lot of things in hash maps, so we are
# using a little of that meta-programmin' magic
# here and saving lots of extra typin'. And since
# many of these attributes above require similar
# functionality to support them, so we again use
# the wonders of meta-programmin' to deliver a
# very compact solution to this normally verbose
# problem.
# - SL
foreach
my
$action
(
{
name
=>
'excluded_roles_map'
,
attr_reader
=>
'get_excluded_roles_map'
,
methods
=> {
add
=>
'add_excluded_roles'
,
get_keys
=>
'get_excluded_roles_list'
,
existence
=>
'excludes_role'
,
}
},
{
name
=>
'required_methods'
,
attr_reader
=>
'get_required_methods_map'
,
methods
=> {
remove
=>
'remove_required_methods'
,
get_values
=>
'get_required_method_list'
,
existence
=>
'requires_method'
,
}
},
) {
my
$attr_reader
=
$action
->{attr_reader};
my
$methods
=
$action
->{methods};
# create the attribute
$META
->add_attribute(
$action
->{name} => (
reader
=>
$attr_reader
,
default
=>
sub
{ {} },
Class::MOP::_definition_context(),
));
# create some helper methods
$META
->add_method(
$methods
->{add} =>
sub
{
my
(
$self
,
@values
) =
@_
;
$self
->
$attr_reader
->{
$_
} =
undef
foreach
@values
;
})
if
exists
$methods
->{add};
$META
->add_method(
$methods
->{get_keys} =>
sub
{
my
(
$self
) =
@_
;
keys
%{
$self
->
$attr_reader
};
})
if
exists
$methods
->{get_keys};
$META
->add_method(
$methods
->{get_values} =>
sub
{
my
(
$self
) =
@_
;
values
%{
$self
->
$attr_reader
};
})
if
exists
$methods
->{get_values};
$META
->add_method(
$methods
->{get} =>
sub
{
my
(
$self
,
$name
) =
@_
;
$self
->
$attr_reader
->{
$name
}
})
if
exists
$methods
->{get};
$META
->add_method(
$methods
->{existence} =>
sub
{
my
(
$self
,
$name
) =
@_
;
exists
$self
->
$attr_reader
->{
$name
} ? 1 : 0;
})
if
exists
$methods
->{existence};
$META
->add_method(
$methods
->{remove} =>
sub
{
my
(
$self
,
@values
) =
@_
;
delete
$self
->
$attr_reader
->{
$_
}
foreach
@values
;
})
if
exists
$methods
->{remove};
}
$META
->add_attribute(
'method_metaclass'
,
reader
=>
'method_metaclass'
,
default
=>
'Moose::Meta::Role::Method'
,
Class::MOP::_definition_context(),
);
$META
->add_attribute(
'required_method_metaclass'
,
reader
=>
'required_method_metaclass'
,
default
=>
'Moose::Meta::Role::Method::Required'
,
Class::MOP::_definition_context(),
);
$META
->add_attribute(
'conflicting_method_metaclass'
,
reader
=>
'conflicting_method_metaclass'
,
default
=>
'Moose::Meta::Role::Method::Conflicting'
,
Class::MOP::_definition_context(),
);
$META
->add_attribute(
'application_to_class_class'
,
reader
=>
'application_to_class_class'
,
default
=>
'Moose::Meta::Role::Application::ToClass'
,
Class::MOP::_definition_context(),
);
$META
->add_attribute(
'application_to_role_class'
,
reader
=>
'application_to_role_class'
,
default
=>
'Moose::Meta::Role::Application::ToRole'
,
Class::MOP::_definition_context(),
);
$META
->add_attribute(
'application_to_instance_class'
,
reader
=>
'application_to_instance_class'
,
default
=>
'Moose::Meta::Role::Application::ToInstance'
,
Class::MOP::_definition_context(),
);
$META
->add_attribute(
'applied_attribute_metaclass'
,
reader
=>
'applied_attribute_metaclass'
,
default
=>
'Moose::Meta::Attribute'
,
Class::MOP::_definition_context(),
);
# More or less copied from Moose::Meta::Class
sub
initialize {
my
$class
=
shift
;
my
@args
=
@_
;
unshift
@args
,
'package'
if
@args
% 2;
my
%opts
=
@args
;
my
$package
=
delete
$opts
{
package
};
return
Class::MOP::get_metaclass_by_name(
$package
)
||
$class
->SUPER::initialize(
$package
,
'attribute_metaclass'
=>
'Moose::Meta::Role::Attribute'
,
%opts
,
);
}
sub
reinitialize {
my
$self
=
shift
;
my
$pkg
=
shift
;
my
$meta
= blessed
$pkg
?
$pkg
: Class::MOP::class_of(
$pkg
);
my
%existing_classes
;
if
(
$meta
) {
%existing_classes
=
map
{
$_
=>
$meta
->
$_
() }
qw(
attribute_metaclass
method_metaclass
wrapped_method_metaclass
required_method_metaclass
conflicting_method_metaclass
application_to_class_class
application_to_role_class
application_to_instance_class
applied_attribute_metaclass
)
;
}
my
%options
=
@_
;
$options
{weaken} = Class::MOP::metaclass_is_weak(
$meta
->name)
if
!
exists
$options
{weaken}
&& blessed(
$meta
)
&&
$meta
->isa(
'Moose::Meta::Role'
);
# don't need to remove generated metaobjects here yet, since we don't
# yet generate anything in roles. this may change in the future though...
# keep an eye on that
my
$new_meta
=
$self
->SUPER::reinitialize(
$pkg
,
%existing_classes
,
%options
,
);
$new_meta
->_restore_metaobjects_from(
$meta
)
if
$meta
&&
$meta
->isa(
'Moose::Meta::Role'
);
return
$new_meta
;
}
sub
_restore_metaobjects_from {
my
$self
=
shift
;
my
(
$old_meta
) =
@_
;
$self
->_restore_metamethods_from(
$old_meta
);
$self
->_restore_metaattributes_from(
$old_meta
);
for
my
$role
( @{
$old_meta
->get_roles } ) {
$self
->add_role(
$role
);
}
}
sub
add_attribute {
my
$self
=
shift
;
if
(blessed
$_
[0] && !
$_
[0]->isa(
'Moose::Meta::Role::Attribute'
) ) {
my
$class
=
ref
$_
[0];
throw_exception(
CannotAddAsAnAttributeToARole
=>
role_name
=>
$self
->name,
attribute_class
=>
$class
,
);
}
elsif
(!blessed(
$_
[0]) &&
defined
(
$_
[0]) &&
$_
[0] =~ /^\+(.*)/) {
throw_exception(
AttributeExtensionIsNotSupportedInRoles
=>
attribute_name
=>
$_
[0],
role_name
=>
$self
->name,
);
}
return
$self
->SUPER::add_attribute(
@_
);
}
sub
_attach_attribute {
my
(
$self
,
$attribute
) =
@_
;
$attribute
->attach_to_role(
$self
);
}
sub
add_required_methods {
my
$self
=
shift
;
for
(
@_
) {
my
$method
=
$_
;
if
(!blessed(
$method
)) {
$method
=
$self
->required_method_metaclass->new(
name
=>
$method
,
);
}
$self
->get_required_methods_map->{
$method
->name} =
$method
;
}
}
sub
add_conflicting_method {
my
$self
=
shift
;
my
$method
;
if
(
@_
== 1 && blessed(
$_
[0])) {
$method
=
shift
;
}
else
{
$method
=
$self
->conflicting_method_metaclass->new(
@_
);
}
$self
->add_required_methods(
$method
);
}
## ------------------------------------------------------------------
## method modifiers
# NOTE:
# the before/around/after method modifiers are
# stored by name, but there can be many methods
# then associated with that name. So again we have
# lots of similar functionality, so we can do some
# meta-programmin' and save some time.
# - SL
foreach
my
$modifier_type
(
qw[ before around after ]
) {
my
$attr_reader
=
"get_${modifier_type}_method_modifiers_map"
;
# create the attribute ...
$META
->add_attribute(
"${modifier_type}_method_modifiers"
=> (
reader
=>
$attr_reader
,
default
=>
sub
{ {} },
Class::MOP::_definition_context(),
));
# and some helper methods ...
$META
->add_method(
"get_${modifier_type}_method_modifiers"
=>
sub
{
my
(
$self
,
$method_name
) =
@_
;
#return () unless exists $self->$attr_reader->{$method_name};
my
$mm
=
$self
->
$attr_reader
->{
$method_name
};
$mm
?
@$mm
: ();
});
$META
->add_method(
"has_${modifier_type}_method_modifiers"
=>
sub
{
my
(
$self
,
$method_name
) =
@_
;
# NOTE:
# for now we assume that if it exists,..
# it has at least one modifier in it
(
exists
$self
->
$attr_reader
->{
$method_name
}) ? 1 : 0;
});
$META
->add_method(
"add_${modifier_type}_method_modifier"
=>
sub
{
my
(
$self
,
$method_name
,
$method
) =
@_
;
$self
->
$attr_reader
->{
$method_name
} = []
unless
exists
$self
->
$attr_reader
->{
$method_name
};
my
$modifiers
=
$self
->
$attr_reader
->{
$method_name
};
# NOTE:
# check to see that we aren't adding the
# same code twice. We err in favor of the
# first on here, this may not be as expected
foreach
my
$modifier
(@{
$modifiers
}) {
return
if
$modifier
==
$method
;
}
push
@{
$modifiers
} =>
$method
;
});
}
## ------------------------------------------------------------------
## override method modifiers
$META
->add_attribute(
'override_method_modifiers'
=> (
reader
=>
'get_override_method_modifiers_map'
,
default
=>
sub
{ {} },
Class::MOP::_definition_context(),
));
# NOTE:
# these are a little different because there
# can only be one per name, whereas the other
# method modifiers can have multiples.
# - SL
sub
add_override_method_modifier {
my
(
$self
,
$method_name
,
$method
) =
@_
;
(!
$self
->has_method(
$method_name
))
|| throw_exception(
CannotOverrideALocalMethod
=>
method_name
=>
$method_name
,
role_name
=>
$self
->name,
);
$self
->get_override_method_modifiers_map->{
$method_name
} =
$method
;
}
sub
has_override_method_modifier {
my
(
$self
,
$method_name
) =
@_
;
# NOTE:
# for now we assume that if it exists,..
# it has at least one modifier in it
(
exists
$self
->get_override_method_modifiers_map->{
$method_name
}) ? 1 : 0;
}
sub
get_override_method_modifier {
my
(
$self
,
$method_name
) =
@_
;
$self
->get_override_method_modifiers_map->{
$method_name
};
}
## general list accessor ...
sub
get_method_modifier_list {
my
(
$self
,
$modifier_type
) =
@_
;
my
$accessor
=
"get_${modifier_type}_method_modifiers_map"
;
keys
%{
$self
->
$accessor
};
}
sub
_meta_method_class {
'Moose::Meta::Method::Meta'
}
## ------------------------------------------------------------------
## subroles
$META
->add_attribute(
'roles'
=> (
reader
=>
'get_roles'
,
default
=>
sub
{ [] },
Class::MOP::_definition_context(),
));
sub
add_role {
my
(
$self
,
$role
) =
@_
;
(blessed(
$role
) &&
$role
->isa(
'Moose::Meta::Role'
))
|| throw_exception(
AddRoleToARoleTakesAMooseMetaRole
=>
role_to_be_added
=>
$role
,
role_name
=>
$self
->name,
);
push
@{
$self
->get_roles} =>
$role
;
$self
->reset_package_cache_flag;
}
sub
calculate_all_roles {
my
$self
=
shift
;
my
%seen
;
grep
{
!
$seen
{
$_
->name}++
} (
$self
,
map
{
$_
->calculate_all_roles
} @{
$self
->get_roles });
}
sub
does_role {
my
(
$self
,
$role
) =
@_
;
(
defined
$role
)
|| throw_exception(
RoleNameRequiredForMooseMetaRole
=>
role_name
=>
$self
->name );
my
$role_name
= blessed
$role
?
$role
->name :
$role
;
# if we are it,.. then return true
return
1
if
$role_name
eq
$self
->name;
# otherwise.. check our children
foreach
my
$role
(@{
$self
->get_roles}) {
return
1
if
$role
->does_role(
$role_name
);
}
return
0;
}
sub
find_method_by_name { (
shift
)->get_method(
@_
) }
## ------------------------------------------------------------------
## role construction
## ------------------------------------------------------------------
sub
apply {
my
(
$self
,
$other
,
%args
) =
@_
;
(blessed(
$other
))
|| throw_exception(
ApplyTakesABlessedInstance
=>
param
=>
$other
,
role_name
=>
$self
->name,
);
my
$application_class
;
if
(
$other
->isa(
'Moose::Meta::Role'
)) {
$application_class
=
$self
->application_to_role_class;
}
elsif
(
$other
->isa(
'Moose::Meta::Class'
)) {
$application_class
=
$self
->application_to_class_class;
}
else
{
$application_class
=
$self
->application_to_instance_class;
}
Moose::Util::_load_user_class(
$application_class
);
if
(
exists
$args
{
'-excludes'
} ) {
# I wish we had coercion here :)
$args
{
'-excludes'
} = (
ref
$args
{
'-excludes'
} eq
'ARRAY'
?
$args
{
'-excludes'
}
: [
$args
{
'-excludes'
} ]
);
}
return
$application_class
->new(
%args
)->apply(
$self
,
$other
, \
%args
);
}
sub
composition_class_roles { }
sub
combine {
my
(
$class
,
@role_specs
) =
@_
;
my
(
@roles
,
%role_params
);
while
(
@role_specs
) {
my
(
$role
,
$params
) = @{
splice
@role_specs
, 0, 1 };
my
$requested_role
= blessed
$role
?
$role
: Class::MOP::class_of(
$role
);
my
$actual_role
=
$requested_role
->_role_for_combination(
$params
);
push
@roles
=>
$actual_role
;
next
unless
defined
$params
;
$role_params
{
$actual_role
->name} =
$params
;
}
my
$c
= Moose::Meta::Role::Composite->new(
roles
=> \
@roles
);
return
$c
->apply_params(\
%role_params
);
}
sub
_role_for_combination {
my
(
$self
,
$params
) =
@_
;
return
$self
;
}
sub
create {
my
$class
=
shift
;
my
@args
=
@_
;
unshift
@args
,
'package'
if
@args
% 2 == 1;
my
%options
=
@args
;
(
ref
$options
{attributes} eq
'HASH'
)
|| throw_exception(
CreateTakesHashRefOfAttributes
=>
params
=> \
%options
,
attribute_class
=>
$class
)
if
exists
$options
{attributes};
(
ref
$options
{methods} eq
'HASH'
)
|| throw_exception(
CreateTakesHashRefOfMethods
=>
params
=> \
%options
,
attribute_class
=>
$class
)
if
exists
$options
{methods};
(
ref
$options
{roles} eq
'ARRAY'
)
|| throw_exception(
CreateTakesArrayRefOfRoles
=>
params
=> \
%options
,
attribute_class
=>
$class
)
if
exists
$options
{roles};
my
$package
=
delete
$options
{
package
};
my
$roles
=
delete
$options
{roles};
my
$attributes
=
delete
$options
{attributes};
my
$methods
=
delete
$options
{methods};
my
$meta_name
=
exists
$options
{meta_name}
?
delete
$options
{meta_name}
:
'meta'
;
my
$meta
=
$class
->SUPER::create(
$package
=>
%options
);
$meta
->_add_meta_method(
$meta_name
)
if
defined
$meta_name
;
if
(
defined
$attributes
) {
foreach
my
$attribute_name
(
keys
%{
$attributes
}) {
my
$attr
=
$attributes
->{
$attribute_name
};
$meta
->add_attribute(
$attribute_name
=> blessed
$attr
?
$attr
: %{
$attr
} );
}
}
if
(
defined
$methods
) {
foreach
my
$method_name
(
keys
%{
$methods
}) {
$meta
->add_method(
$method_name
,
$methods
->{
$method_name
});
}
}
if
(
$roles
) {
Moose::Util::apply_all_roles(
$meta
,
@$roles
);
}
return
$meta
;
}
sub
consumers {
my
$self
=
shift
;
my
@consumers
;
for
my
$meta
(Class::MOP::get_all_metaclass_instances) {
next
if
$meta
->name eq
$self
->name;
next
unless
$meta
->isa(
'Moose::Meta::Class'
)
||
$meta
->isa(
'Moose::Meta::Role'
);
push
@consumers
,
$meta
->name
if
$meta
->does_role(
$self
->name);
}
return
@consumers
;
}
# XXX: something more intelligent here?
sub
_anon_package_prefix {
'Moose::Meta::Role::__ANON__::SERIAL::'
}
sub
create_anon_role {
shift
->create_anon(
@_
) }
sub
is_anon_role {
shift
->is_anon(
@_
) }
sub
_anon_cache_key {
my
$class
=
shift
;
my
%options
=
@_
;
# XXX fix this duplication (see MMC::_anon_cache_key
my
$roles
= Data::OptList::mkopt((
$options
{roles} || []), {
moniker
=>
'role'
,
val_test
=>
sub
{
ref
(
$_
[0]) eq
'HASH'
},
});
my
@role_keys
;
for
my
$role_spec
(
@$roles
) {
my
(
$role
,
$params
) =
@$role_spec
;
$params
= {
%$params
};
my
$key
= blessed(
$role
) ?
$role
->name :
$role
;
if
(
$params
&&
%$params
) {
my
$alias
=
delete
$params
->{
'-alias'
}
||
delete
$params
->{
'alias'
}
|| {};
my
$excludes
=
delete
$params
->{
'-excludes'
}
||
delete
$params
->{
'excludes'
}
|| [];
$excludes
= [
$excludes
]
unless
ref
(
$excludes
) eq
'ARRAY'
;
if
(
%$params
) {
warn
"Roles with parameters cannot be cached. Consider "
.
"applying the parameters before calling "
.
"create_anon_class, or using 'weaken => 0' instead"
;
return
;
}
my
$alias_key
=
join
(
'%'
,
map
{
$_
=>
$alias
->{
$_
} }
sort
keys
%$alias
);
my
$excludes_key
=
join
(
'%'
,
sort
@$excludes
);
$key
.=
'<'
.
join
(
'+'
,
'a'
,
$alias_key
,
'e'
,
$excludes_key
) .
'>'
;
}
push
@role_keys
,
$key
;
}
# Makes something like Role|Role::1
return
join
(
'|'
,
sort
@role_keys
);
}
#####################################################################
## NOTE:
## This is Moose::Meta::Role as defined by Moose (plus the use of
## MooseX::AttributeHelpers module). It is here as a reference to
## make it easier to see what is happening above with all the meta
## programming. - SL
#####################################################################
#
# has 'roles' => (
# metaclass => 'Array',
# reader => 'get_roles',
# isa => 'ArrayRef[Moose::Meta::Role]',
# default => sub { [] },
# provides => {
# 'push' => 'add_role',
# }
# );
#
# has 'excluded_roles_map' => (
# metaclass => 'Hash',
# reader => 'get_excluded_roles_map',
# isa => 'HashRef[Str]',
# provides => {
# # Not exactly set, cause it sets multiple
# 'set' => 'add_excluded_roles',
# 'keys' => 'get_excluded_roles_list',
# 'exists' => 'excludes_role',
# }
# );
#
# has 'required_methods' => (
# metaclass => 'Hash',
# reader => 'get_required_methods_map',
# isa => 'HashRef[Moose::Meta::Role::Method::Required]',
# provides => {
# # not exactly set, or delete since it works for multiple
# 'set' => 'add_required_methods',
# 'delete' => 'remove_required_methods',
# 'keys' => 'get_required_method_list',
# 'exists' => 'requires_method',
# }
# );
#
# # the before, around and after modifiers are
# # HASH keyed by method-name, with ARRAY of
# # CODE refs to apply in that order
#
# has 'before_method_modifiers' => (
# metaclass => 'Hash',
# reader => 'get_before_method_modifiers_map',
# isa => 'HashRef[ArrayRef[CodeRef]]',
# provides => {
# 'keys' => 'get_before_method_modifiers',
# 'exists' => 'has_before_method_modifiers',
# # This actually makes sure there is an
# # ARRAY at the given key, and pushed onto
# # it. It also checks for duplicates as well
# # 'add' => 'add_before_method_modifier'
# }
# );
#
# has 'after_method_modifiers' => (
# metaclass => 'Hash',
# reader =>'get_after_method_modifiers_map',
# isa => 'HashRef[ArrayRef[CodeRef]]',
# provides => {
# 'keys' => 'get_after_method_modifiers',
# 'exists' => 'has_after_method_modifiers',
# # This actually makes sure there is an
# # ARRAY at the given key, and pushed onto
# # it. It also checks for duplicates as well
# # 'add' => 'add_after_method_modifier'
# }
# );
#
# has 'around_method_modifiers' => (
# metaclass => 'Hash',
# reader =>'get_around_method_modifiers_map',
# isa => 'HashRef[ArrayRef[CodeRef]]',
# provides => {
# 'keys' => 'get_around_method_modifiers',
# 'exists' => 'has_around_method_modifiers',
# # This actually makes sure there is an
# # ARRAY at the given key, and pushed onto
# # it. It also checks for duplicates as well
# # 'add' => 'add_around_method_modifier'
# }
# );
#
# # override is similar to the other modifiers
# # except that it is not an ARRAY of code refs
# # but instead just a single name->code mapping
#
# has 'override_method_modifiers' => (
# metaclass => 'Hash',
# reader =>'get_override_method_modifiers_map',
# isa => 'HashRef[CodeRef]',
# provides => {
# 'keys' => 'get_override_method_modifier',
# 'exists' => 'has_override_method_modifier',
# 'add' => 'add_override_method_modifier', # checks for local method ..
# }
# );
#
#####################################################################
1;
# ABSTRACT: The Moose Role metaclass
__END__
=pod
=encoding UTF-8
=head1 NAME
Moose::Meta::Role - The Moose Role metaclass
=head1 VERSION
version 2.2207
=head1 DESCRIPTION
This class is a subclass of L<Class::MOP::Module> that provides
additional Moose-specific functionality.
Its API looks a lot like L<Moose::Meta::Class>, but internally it
implements many things differently. This may change in the future.
=head1 INHERITANCE
C<Moose::Meta::Role> is a subclass of L<Class::MOP::Module>.
=head1 METHODS
=head2 Construction
=head3 Moose::Meta::Role->initialize($role_name)
This method creates a new role object with the provided name.
=head3 Moose::Meta::Role->combine( [ $role => { ... } ], [ $role ], ... )
This method accepts a list of array references. Each array reference
should contain a role name or L<Moose::Meta::Role> object as its first element. The second element is
an optional hash reference. The hash reference can contain C<-excludes>
and C<-alias> keys to control how methods are composed from the role.
The return value is a new L<Moose::Meta::Role::Composite> that
represents the combined roles.
=head3 $metarole->composition_class_roles
When combining multiple roles using C<combine>, this method is used to obtain a
list of role names to be applied to the L<Moose::Meta::Role::Composite>
instance returned by C<combine>. The default implementation returns an empty
list. Extensions that need to hook into role combination may wrap this method
to return additional role names.
=head3 Moose::Meta::Role->create($name, %options)
This method is identical to the L<Moose::Meta::Class> C<create>
method.
=head3 Moose::Meta::Role->create_anon_role
This method is identical to the L<Moose::Meta::Class>
C<create_anon_class> method.
=head3 $metarole->is_anon_role
Returns true if the role is an anonymous role.
=head3 $metarole->consumers
Returns a list of names of classes and roles which consume this role.
=head2 Role application
=head3 $metarole->apply( $thing, @options )
This method applies a role to the given C<$thing>. That can be another
L<Moose::Meta::Role>, object, a L<Moose::Meta::Class> object, or a
(non-meta) object instance.
The options are passed directly to the constructor for the appropriate
L<Moose::Meta::Role::Application> subclass.
Note that this will apply the role even if the C<$thing> in question already
C<does> this role. L<Moose::Util/does_role> is a convenient wrapper for
finding out if role application is necessary.
=head2 Roles and other roles
=head3 $metarole->get_roles
This returns an array reference of roles which this role does. This
list may include duplicates.
=head3 $metarole->calculate_all_roles
This returns a I<unique> list of all roles that this role does, and
all the roles that its roles do.
=head3 $metarole->does_role($role)
Given a role I<name> or L<Moose::Meta::Role> object, returns true if this role
does the given role.
=head3 $metarole->add_role($role)
Given a L<Moose::Meta::Role> object, this adds the role to the list of
roles that the role does.
=head3 $metarole->get_excluded_roles_list
Returns a list of role names which this role excludes.
=head3 $metarole->excludes_role($role_name)
Given a role I<name>, returns true if this role excludes the named
role.
=head3 $metarole->add_excluded_roles(@role_names)
Given one or more role names, adds those roles to the list of excluded
roles.
=head2 Methods
The methods for dealing with a role's methods are all identical in API
and behavior to the same methods in L<Class::MOP::Class>.
=head3 $metarole->method_metaclass
Returns the method metaclass name for the role. This defaults to
L<Moose::Meta::Role::Method>.
=head3 $metarole->get_method($name)
=head3 $metarole->has_method($name)
=head3 $metarole->add_method( $name, $body )
=head3 $metarole->get_method_list
=head3 $metarole->find_method_by_name($name)
These methods are all identical to the methods of the same name in
L<Class::MOP::Class>
=head2 Attributes
As with methods, the methods for dealing with a role's attribute are
all identical in API and behavior to the same methods in
L<Class::MOP::Class>.
However, attributes stored in this class are I<not> stored as
objects. Rather, the attribute definition is stored as a hash
reference. When a role is composed into a class, this hash reference
is passed directly to the metaclass's C<add_attribute> method.
This is quite likely to change in the future.
=head3 $metarole->get_attribute($attribute_name)
=head3 $metarole->has_attribute($attribute_name)
=head3 $metarole->get_attribute_list
=head3 $metarole->add_attribute($name, %options)
=head3 $metarole->remove_attribute($attribute_name)
=head2 Overload introspection and creation
The methods for dealing with a role's overloads are all identical in API and
behavior to the same methods in L<Class::MOP::Class>.
=head3 $metarole->is_overloaded
=head3 $metarole->get_overloaded_operator($op)
=head3 $metarole->has_overloaded_operator($op)
=head3 $metarole->get_overload_list
=head3 $metarole->get_all_overloaded_operators
=head3 $metarole->add_overloaded_operator($op, $impl)
=head3 $metarole->remove_overloaded_operator($op)
=head2 Required methods
=head3 $metarole->get_required_method_list
Returns the list of methods required by the role.
=head3 $metarole->requires_method($name)
Returns true if the role requires the named method.
=head3 $metarole->add_required_methods(@names)
Adds the named methods to the role's list of required methods.
=head3 $metarole->remove_required_methods(@names)
Removes the named methods from the role's list of required methods.
=head3 $metarole->add_conflicting_method(%params)
Instantiate the parameters as a L<Moose::Meta::Role::Method::Conflicting>
object, then add it to the required method list.
=head2 Method modifiers
These methods act like their counterparts in L<Class::MOP::Class> and
L<Moose::Meta::Class>.
However, method modifiers are simply stored internally, and are not applied
until the role itself is applied to a class or object.
=head3 $metarole->add_after_method_modifier($method_name, $method)
=head3 $metarole->add_around_method_modifier($method_name, $method)
=head3 $metarole->add_before_method_modifier($method_name, $method)
=head3 $metarole->add_override_method_modifier($method_name, $method)
These methods all add an appropriate modifier to the internal list of
modifiers.
=head3 $metarole->has_after_method_modifiers
=head3 $metarole->has_around_method_modifiers
=head3 $metarole->has_before_method_modifiers
=head3 $metarole->has_override_method_modifier
Return true if the role has any modifiers of the given type.
=head3 $metarole->get_after_method_modifiers($method_name)
=head3 $metarole->get_around_method_modifiers($method_name)
=head3 $metarole->get_before_method_modifiers($method_name)
Given a method name, returns a list of the appropriate modifiers for
that method.
=head3 $metarole->get_override_method_modifier($method_name)
Given a method name, returns the override method modifier for that
method, if it has one.
=head2 Introspection
=head3 Moose::Meta::Role->meta
This will return a L<Class::MOP::Class> instance for this class.
=head1 BUGS
See L<Moose/BUGS> for details on reporting bugs.
=head1 AUTHORS
=over 4
=item *
Stevan Little <stevan@cpan.org>
=item *
Dave Rolsky <autarch@urth.org>
=item *
Jesse Luehrs <doy@cpan.org>
=item *
Shawn M Moore <sartak@cpan.org>
=item *
יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
=item *
Karen Etheridge <ether@cpan.org>
=item *
Florian Ragwitz <rafl@debian.org>
=item *
Hans Dieter Pearcey <hdp@cpan.org>
=item *
Chris Prather <chris@prather.org>
=item *
Matt S Trout <mstrout@cpan.org>
=back
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2006 by Infinity Interactive, Inc.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut