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