more readable inlined code
[gitmo/Moose.git] / lib / Moose / Meta / TypeConstraint / Role.pm
CommitLineData
620db045 1package Moose::Meta::TypeConstraint::Role;
2
3use strict;
4use warnings;
5use metaclass;
6
089455fc 7use B;
620db045 8use Scalar::Util 'blessed';
9use Moose::Util::TypeConstraints ();
10
620db045 11use base 'Moose::Meta::TypeConstraint';
12
13__PACKAGE__->meta->add_attribute('role' => (
14 reader => 'role',
15));
16
089455fc 17my $inliner = sub {
18 my $self = shift;
19 my $val = shift;
20
3975b592 21 return 'Moose::Util::does_role('
22 . $val . ', '
23 . B::perlstring($self->role)
24 . ')';
089455fc 25};
26
620db045 27sub new {
28 my ( $class, %args ) = @_;
29
f37d0936 30 $args{parent} = Moose::Util::TypeConstraints::find_type_constraint('Object');
7ae2d933 31
32 my $role_name = $args{role};
33 $args{constraint} = sub { Moose::Util::does_role( $_[0], $role_name ) };
34
089455fc 35 $args{inlined} = $inliner;
36
7ae2d933 37 my $self = $class->_new( \%args );
620db045 38
39 $self->_create_hand_optimized_type_constraint;
40 $self->compile_type_constraint();
41
42 return $self;
43}
44
45sub _create_hand_optimized_type_constraint {
46 my $self = shift;
47 my $role = $self->role;
48 $self->hand_optimized_type_constraint(
49 sub { Moose::Util::does_role($_[0], $role) }
50 );
51}
52
53sub parents {
54 my $self = shift;
55 return (
56 $self->parent,
57 map {
58 # FIXME find_type_constraint might find a TC named after the role but that isn't really it
59 # I did this anyway since it's a convention that preceded TypeConstraint::Role, and it should DWIM
60 # if anybody thinks this problematic please discuss on IRC.
61 # a possible fix is to add by attr indexing to the type registry to find types of a certain property
62 # regardless of their name
d03bd989 63 Moose::Util::TypeConstraints::find_type_constraint($_)
64 ||
620db045 65 __PACKAGE__->new( role => $_, name => "__ANON__" )
1551760b 66 } @{ Class::MOP::class_of($self->role)->get_roles },
620db045 67 );
68}
69
70sub equals {
71 my ( $self, $type_or_name ) = @_;
72
73 my $other = Moose::Util::TypeConstraints::find_type_constraint($type_or_name);
74
4c015454 75 return unless defined $other;
620db045 76 return unless $other->isa(__PACKAGE__);
77
78 return $self->role eq $other->role;
79}
80
81sub is_a_type_of {
82 my ($self, $type_or_name) = @_;
83
8d33489c 84 my $type = Moose::Util::TypeConstraints::find_type_constraint($type_or_name);
620db045 85
86 ($self->equals($type) || $self->is_subtype_of($type_or_name));
87}
88
89sub is_subtype_of {
90 my ($self, $type_or_name_or_role ) = @_;
91
92 if ( not ref $type_or_name_or_role ) {
93 # it might be a role
6f84b038 94 return 1 if Class::MOP::class_of($self->role)->does_role( $type_or_name_or_role );
620db045 95 }
96
97 my $type = Moose::Util::TypeConstraints::find_type_constraint($type_or_name_or_role);
98
4c015454 99 return unless defined $type;
d03bd989 100
620db045 101 if ( $type->isa(__PACKAGE__) ) {
102 # if $type_or_name_or_role isn't a role, it might be the TC name of another ::Role type
103 # or it could also just be a type object in this branch
db6ace79 104 return Class::MOP::class_of($self->role)->does_role( $type->role );
620db045 105 } else {
106 # the only other thing we are a subtype of is Object
107 $self->SUPER::is_subtype_of($type);
108 }
109}
110
2fb4885e 111sub create_child_type {
112 my ($self, @args) = @_;
39170e48 113 return Moose::Meta::TypeConstraint->new(@args, parent => $self);
2fb4885e 114}
115
620db045 1161;
117
ad46f524 118# ABSTRACT: Role/TypeConstraint parallel hierarchy
119
620db045 120__END__
121
122=pod
123
3cb26ff4 124=head1 DESCRIPTION
125
126This class represents type constraints for a role.
127
128=head1 INHERITANCE
129
130C<Moose::Meta::TypeConstraint::Role> is a subclass of
131L<Moose::Meta::TypeConstraint>.
132
620db045 133=head1 METHODS
134
135=over 4
136
3cb26ff4 137=item B<< Moose::Meta::TypeConstraint::Role->new(%options) >>
138
139This creates a new role type constraint based on the given
140C<%options>.
141
142It takes the same options as its parent, with two exceptions. First,
143it requires an additional option, C<role>, which is name of the
144constraint's role. Second, it automatically sets the parent to the
145C<Object> type.
146
147The constructor also overrides the hand optimized type constraint with
148one it creates internally.
620db045 149
3cb26ff4 150=item B<< $constraint->role >>
620db045 151
3cb26ff4 152Returns the role name associated with the constraint.
620db045 153
3cb26ff4 154=item B<< $constraint->parents >>
620db045 155
3cb26ff4 156Returns all the type's parent types, corresponding to the roles that
157its role does.
620db045 158
2870fb09 159=item B<< $constraint->is_subtype_of($type_name_or_object) >>
620db045 160
3cb26ff4 161If the given type is also a role type, then this checks that the
162type's role does the other type's role.
620db045 163
3cb26ff4 164Otherwise it falls back to the implementation in
165L<Moose::Meta::TypeConstraint>.
2fb4885e 166
3cb26ff4 167=item B<< $constraint->create_child_type(%options) >>
620db045 168
3cb26ff4 169This returns a new L<Moose::Meta::TypeConstraint> object with the type
170as its parent.
620db045 171
3cb26ff4 172Note that it does I<not> return a C<Moose::Meta::TypeConstraint::Role>
173object!
620db045 174
175=back
176
177=head1 BUGS
178
d4048ef3 179See L<Moose/BUGS> for details on reporting bugs.
620db045 180
620db045 181=cut