File Coverage

blib/lib/MooseX/XSAccessor/Trait/Attribute.pm
Criterion Covered Total %
statement 45 46 97.8
branch 21 24 87.5
condition 5 6 83.3
subroutine 13 14 92.8
pod 5 5 100.0
total 89 95 93.6


line stmt bran cond sub pod time code
1             package MooseX::XSAccessor::Trait::Attribute;
2              
3 42     42   569 use 5.008;
  42         130  
4 42     42   198 use strict;
  42         78  
  42         776  
5 42     42   173 use warnings;
  42         95  
  42         1069  
6              
7 42     42   16249 use Class::XSAccessor 1.09 ();
  42         79874  
  42         1159  
8 42     42   280 use Scalar::Util qw(reftype);
  42         81  
  42         2455  
9 42     42   241 use B qw(perlstring);
  42         79  
  42         2228  
10              
11             BEGIN {
12 42     42   130 $MooseX::XSAccessor::Trait::Attribute::AUTHORITY = 'cpan:TOBYINK';
13 42         1811 $MooseX::XSAccessor::Trait::Attribute::VERSION = '0.008';
14             }
15              
16             # Map Moose terminology to Class::XSAccessor options.
17             my %cxsa_opt = (
18             accessor => "accessors",
19             reader => "getters",
20             writer => "setters",
21             );
22              
23             $cxsa_opt{predicate} = "exists_predicates"
24             if Class::XSAccessor->VERSION > 1.16;
25              
26 42     42   12080 use Moose::Role;
  42         154419  
  42         176  
27              
28             sub accessor_is_simple
29             {
30 59     59 1 126 my $self = shift;
31 59 100 100     1958 return !!0 if $self->has_type_constraint && $self->type_constraint ne "Any";
32 27 50       1005 return !!0 if $self->should_coerce;
33 27 100       985 return !!0 if $self->has_trigger;
34 23 100       773 return !!0 if $self->is_weak_ref;
35 22 100       785 return !!0 if $self->is_lazy;
36 20 50       743 return !!0 if $self->should_auto_deref;
37 20         196 !!1;
38             }
39              
40             sub reader_is_simple
41             {
42 82     82 1 167 my $self = shift;
43 82 100       2504 return !!0 if $self->is_lazy;
44 67 100       2569 return !!0 if $self->should_auto_deref;
45 63         591 !!1;
46             }
47              
48             sub writer_is_simple
49             {
50 14     14 1 32 my $self = shift;
51 14 100 66     509 return !!0 if $self->has_type_constraint && $self->type_constraint ne "Any";
52 9 50       326 return !!0 if $self->should_coerce;
53 9 100       353 return !!0 if $self->has_trigger;
54 8 100       311 return !!0 if $self->is_weak_ref;
55 7         107 !!1;
56             }
57              
58             sub predicate_is_simple
59             {
60 13     13 1 36 my $self = shift;
61 13         44 !!1;
62             }
63              
64             # Class::XSAccessor doesn't do clearers
65             sub clearer_is_simple
66             {
67 0     0 1   !!0;
68             }
69              
70             after install_accessors => sub {
71             my $self = shift;
72            
73             my $slot = $self->name;
74             my $class = $self->associated_class;
75             my $classname = $class->name;
76            
77             # Don't attempt to do anything with instances that are not blessed hashes.
78             my $is_hash = reftype($class->get_meta_instance->create_instance) eq q(HASH);
79             return unless $is_hash && $class->get_meta_instance->is_inlinable;
80            
81             # Use inlined get method as a heuristic to detect weird shit.
82             my $inline_get = $self->_inline_instance_get('$X');
83             return unless $inline_get eq sprintf('$X->{%s}', perlstring $slot);
84            
85             # Detect use of MooseX::Attribute::Chained
86             my $is_chained = $self->does('MooseX::Traits::Attribute::Chained');
87            
88             # Detect use of MooseX::LvalueAttribute
89             my $is_lvalue = $self->does('MooseX::LvalueAttribute::Trait::Attribute');
90            
91             for my $type (qw/ accessor reader writer predicate clearer /)
92             {
93             # Only accelerate methods if CXSA can deal with them
94             next unless exists $cxsa_opt{$type};
95            
96             # Only accelerate methods that exist!
97             next unless $self->${\"has_$type"};
98            
99             # Check to see they're simple (no type constraint checks, etc)
100             next unless $self->${\"$type\_is_simple"};
101            
102             my $methodname = $self->$type;
103             my $metamethod = $class->get_method($methodname);
104            
105             # Perform the actual acceleration
106             if ($type eq 'accessor' and $is_lvalue)
107             {
108             next if $is_chained;
109             next if !$MooseX::XSAccessor::LVALUE;
110            
111             "Class::XSAccessor"->import(
112             class => $classname,
113             replace => 1,
114             lvalue_accessors => +{ $methodname => $slot },
115             );
116             }
117             else
118             {
119             "Class::XSAccessor"->import(
120             class => $classname,
121             replace => 1,
122             chained => $is_chained,
123             $cxsa_opt{$type} => +{ $methodname => $slot },
124             );
125             }
126            
127             # Naughty stuff!!!
128             # We've overwritten a Moose-generated accessor, so now we need to
129             # inform Moose's metathingies about the new coderef.
130             # $metamethod->body is read-only, so dive straight into the blessed
131             # hash.
132 42     42   231367 no strict "refs";
  42         103  
  42         5328  
133             $metamethod->{"body"} = \&{"$classname\::$methodname"};
134             }
135            
136             return;
137             };
138              
139             1;
140              
141             __END__
142              
143             =pod
144              
145             =for stopwords booleans
146              
147             =encoding utf-8
148              
149             =head1 NAME
150              
151             MooseX::XSAccessor::Trait::Attribute - get the Class::XSAccessor effect for a single attribute
152              
153             =head1 SYNOPSIS
154              
155             package MyClass;
156            
157             use Moose;
158            
159             has foo => (
160             traits => ["MooseX::XSAccessor::Trait::Attribute"],
161             ...,
162             );
163            
164             say __PACKAGE__->meta->get_attribute("foo")->accessor_is_simple;
165              
166             =head1 DESCRIPTION
167              
168             Attributes with this trait have the following additional methods, which
169             each return booleans:
170              
171             =over
172              
173             =item C<< accessor_is_simple >>
174              
175             =item C<< reader_is_simple >>
176              
177             =item C<< writer_is_simple >>
178              
179             =item C<< predicate_is_simple >>
180              
181             =item C<< clearer_is_simple >>
182              
183             =back
184              
185             What is meant by simple? Simple enough for L<Class::XSAccessor> to take
186             over the accessor's duties.
187              
188             =head1 BUGS
189              
190             Please report any bugs to
191             L<http://rt.cpan.org/Dist/Display.html?Queue=MooseX-XSAccessor>.
192              
193             =head1 SEE ALSO
194              
195             L<MooseX::XSAccessor>.
196              
197             =head1 AUTHOR
198              
199             Toby Inkster E<lt>tobyink@cpan.orgE<gt>.
200              
201             =head1 COPYRIGHT AND LICENCE
202              
203             This software is copyright (c) 2013 by Toby Inkster.
204              
205             This is free software; you can redistribute it and/or modify it under
206             the same terms as the Perl 5 programming language system itself.
207              
208             =head1 DISCLAIMER OF WARRANTIES
209              
210             THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
211             WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
212             MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
213