File Coverage

blib/lib/Class/Trait.pm
Criterion Covered Total %
statement 1023 1023 100.0
branch 192 314 61.1
condition 10 18 55.5
subroutine 341 341 100.0
pod 2 25 8.0
total 1568 1721 91.1


line stmt bran cond sub pod time code
1             package Class::Trait;
2              
3 15     15   422664 use strict;
  15     2   38  
  15     1   566  
  2     1   9  
  1     1   1  
  2     1   25  
  1     1   6  
  1     1   2  
  1     1   20  
  1     1   4  
  1         2  
  1         20  
  1         5  
  1         2  
  1         27  
  1         5  
  1         1  
  1         20  
4 15     15   82 use warnings;
  15     1   28  
  15     1   1264  
  1     1   4  
  1     1   2  
  2     1   264  
  1     1   4  
  1     1   3  
  1     1   234  
  1     1   4  
  1         2  
  1         234  
  1         8  
  1         2  
  1         247  
  1         5  
  1         2  
  1         268  
5              
6             our $VERSION = '0.31';
7              
8 15     15   16181 use overload ();
  15     2   10857  
  15     1   276  
  1     1   6  
  2     1   7  
  1     1   55  
  1     1   4  
  1     1   3  
  1     1   52  
  1     1   5  
  1         2  
  1         56  
  1         5  
  1         1  
  1         55  
  1         5  
  1         1  
  1         53  
9 15     15   109 use File::Spec ();
  15     1   24  
  15     1   396  
  2     1   967  
  2     1   998  
  1     1   293  
  1     1   4  
  1     1   2  
  1     1   339  
  1     1   4  
  1         3  
  1         298  
  1         4  
  1         2  
  1         304  
  1         4  
  1         4  
  1         305  
10              
11 15     15   80 use B qw/svref_2object/;
  15     1   26  
  15     1   1216  
  2     1   1002  
  1     1   2  
  1     1   715  
  1     1   5  
  1     1   2  
  1     1   700  
  1     1   5  
  1         2  
  1         652  
  1         5  
  1         2  
  1         689  
  1         4  
  1         2  
  1         716  
12 15     15   87 use Scalar::Util qw/blessed/;
  15     2   28  
  15     1   7680  
  1     1   5  
  1     1   2  
  1     1   33  
  1     1   5  
  1     1   2  
  1     1   23  
  1         6  
  1         1  
  1         22  
  1         5  
  1         2  
  1         41  
  1         5  
  1         3  
  1         27  
13              
14             sub _croak($) {
15 9     10   25 my $message = shift;
16 9         80 require Carp;
17 10         1710 Carp::croak($message);
18             }
19              
20             sub _sub_package {
21 103     127   115 my $package;
22 103         214 eval {
23 103         759 my $stash = svref_2object(shift)->STASH;
24 103 100 33     1041 if ( $stash && $stash->can('NAME') ) {
25 105         466 $package = $stash->NAME;
26             }
27             else {
28 2         8 $package = '';
29             }
30             };
31 102 50       228 if ($@) {
32 2         21 warn "Could not determine calling package: $@";
33             }
34 127         455 return $package;
35             }
36              
37             ## ----------------------------------------------------------------------------
38             ## Debugging functions
39             ## ----------------------------------------------------------------------------
40              
41             # make a sub
42 1793     1793 0 11943 sub DEBUG {0}
43             require Data::Dumper if DEBUG;
44              
45             # this is accessable to the package
46             my $debug_indent = 0;
47              
48             {
49              
50             # this however is not accessable to anyone but the debug function
51             my $debug_line_number = 1;
52              
53             # debuggin'
54             sub debug {
55 1 0   1 0 48 return unless DEBUG;
56              
57             # otherwise debug
58 1         4 my $formatted_debug_line_number
59             = sprintf( "%03d", $debug_line_number );
60 1         1 print STDERR "debug=($formatted_debug_line_number) ",
61             ( " " x $debug_indent ), @_, "\n";
62 1         273 $debug_line_number++;
63             }
64             }
65              
66             ## ----------------------------------------------------------------------------
67              
68             # This allows us to rename "does" to something which does not conflict with a
69             # method in the current package. Also, for backwards compatability, one can
70             # specifiy Class::Trait->relation('is');
71              
72             my $NAME_FOR_DOES = 'does';
73              
74             sub _name_for_does {
75 2     2   881 $NAME_FOR_DOES;
76             }
77              
78             # XXX OK, admit it. This function is a right mess. I'm embarrassed.
79             my %PACKAGE_DOES;
80             my $DOES = sub {
81 52     51   26982 my $proto = shift;
82 52   66     341 my $class = ref($proto) || $proto;
83 52         186 my $trait;
84 52 50       466 if ( !$proto->isa('Class::Trait::Config') ) {
85 15     15   98 no strict 'refs';
  15     1   40  
  15     1   3373  
  1     1   4  
  1     1   3  
  1     1   130  
  1     1   12  
  1     1   2  
  1     1   139  
  1         4  
  1         2  
  1         162  
  1         5  
  1         2  
  1         129  
  1         4  
  1         2  
  1         130  
86 52 100       187 $trait = ${"${class}::TRAITS"} or do {
  51         254  
87            
88             # if we've gotten to here, then the TRAITS are not defined in the
89             # current package. This implies that we have a subclass
90             # inheriting from a class which uses traits and the does() method
91             # needs to search the inheritance heirarchy.
92 4         7 foreach my $parent ( @{"${class}::ISA"} ) {
  4         138  
93 4 50       137 my @result = $parent->$NAME_FOR_DOES(@_)
94             if $parent->can($NAME_FOR_DOES);
95 4 50       16 next unless @result;
96 4 100       18 if (@_) {
97 4   66     127 return $result[0] || ();
98             }
99 1         2 return @result;
100             }
101             };
102             }
103             else {
104 2         136 $trait = $proto;
105             }
106 49 100       115 if (@_) {
107 45         69 my $trait_name = shift;
108 45 100       179 if ( exists $PACKAGE_DOES{$class}{$trait_name} ) {
109 30         180 return 1;
110             }
111 15         153 my $does = _recursive_does( $trait, $trait_name );
112 15 100       256 return $does if $does;
113              
114             # we have runtime traits applied to instances
115 8 100       34 if ( $class =~ /__ANON__/ ) {
116 15     15   82 no strict 'refs';
  15     2   36  
  15     1   2191  
  1     1   5  
  1     1   1  
  1     1   21  
  1     1   5  
  1     1   2  
  1     1   33  
  1         4  
  1         2  
  1         21  
  1         4  
  1         1  
  1         21  
  1         5  
  1         1  
  1         21  
117 3         344 ($class)
118 3         6 = @{"${class}::ISA"}; # ANON traits have single inheritance
119 3 100       38 return $class->$NAME_FOR_DOES($trait_name)
120             if $class->can($NAME_FOR_DOES);
121             }
122 7         27 return $does;
123             }
124             else {
125 12         36 my %does = map { $_ => 1 } _all_does($trait),
  5         19  
126 5         228 keys %{ $PACKAGE_DOES{$class} };
127              
128             # we have runtime traits applied to instances
129 5 100       598 if ( $class =~ /__ANON__/ ) {
130 15     15   89 no strict 'refs';
  15     1   36  
  15     1   2946  
  1     1   5  
  1     1   1  
  1     1   638  
  1     1   5  
  1     1   2  
  1     1   634  
  1         4  
  1         1  
  1         617  
  1         4  
  1         7  
  1         627  
  1         4  
  1         2  
  1         595  
131 3         14 ($class)
132 3         82 = @{"${class}::ISA"}; # ANON traits have single inheritance
133 3 100       175 if ( $class->can($NAME_FOR_DOES) ) {
134 2         8 foreach my $does ( $class->$NAME_FOR_DOES ) {
135 2         6 $does{$does} = 1;
136             }
137             }
138 3 100       37 if ( exists $PACKAGE_DOES{$class} ) {
139 2         6 foreach my $does ( keys %{ $PACKAGE_DOES{$class} } ) {
  2         4  
140 2         245 $does{$does} = 1;
141             }
142             }
143             }
144 5         42 return keys %does;
145             }
146             };
147              
148             # a trait cache, so we can avoid re-processing traits we already have
149             # processed. This is checked by the trait_load function prior to reading the
150             # trait in
151              
152             my %CACHE = ();
153              
154             # load the config class
155 15     15   9769 use Class::Trait::Config;
  15     2   53  
  15     1   128  
  1     1   6  
  1     1   1  
  1     1   171  
  1     1   6  
  1     1   4  
  1     1   194  
  1         5  
  1         2  
  1         155  
  1         5  
  1         2  
  1         155  
  1         5  
  1         1  
  1         197  
156              
157             # base class for traits
158 15     15   10159 use Class::Trait::Base;
  15     2   42  
  15     1   2530  
  1     1   5  
  1     1   2  
  1     1   187  
  1     1   7  
  1     1   2  
  1     1   225  
  1         5  
  1         3  
  1         201  
  1         5  
  1         2  
  1         214  
  1         5  
  1         2  
  1         187  
159              
160             # save packages that need to be checked for meeting requirements here
161              
162             my %TRAITS_TO_CHECK = ();
163              
164             sub _clear_all_caches {
165 74     74   14349 %CACHE = ();
166 74         193 %TRAITS_TO_CHECK = ();
167             }
168              
169             # XXX this is merely a testing hook
170             sub _clear_does_cache {
171 59     59   228 %PACKAGE_DOES = ();
172             }
173              
174             # these traits are supplied "for free"
175              
176             my $TRAIT_LIB_ROOT = File::Spec->catfile(qw(Class Trait Lib));
177              
178             my %TRAIT_LIB = map { $_ => 1 }
179             qw(
180             TEquality
181             TPrintable
182             TComparable
183             );
184              
185             ## ----------------------------------------------------------------------------
186              
187             sub import {
188 72     70   7544 my $class = shift;
189              
190             # just loading the module does not mean we have any traits to give it, so
191             # we return if there is nothing
192 72 100       1456 return unless @_;
193              
194             # but if we have something, then ...
195 70         199 my ($package) = caller();
196              
197             # if we are being asked to make a trait a trait then ...
198 68 100       271 if ( $_[0] eq "debug" ) {
    100          
199 15     15   80 no strict 'refs';
  15     1   28  
  15     1   441  
  1     1   5  
  1     1   2  
  1     1   67  
  1     1   6  
  1     1   2  
  1     1   78  
  1         6  
  1         2  
  1         63  
  1         5  
  1         1  
  1         67  
  1         4  
  1         2  
  1         64  
200 15     15   79 no warnings 'redefine';
  15     2   58  
  15     1   1028  
  1     1   5  
  1     1   1  
  1     1   487  
  1     1   4  
  1     1   2  
  1     1   542  
  1         5  
  1         1  
  1         491  
  1         5  
  1         2  
  1         514  
  1         4  
  1         3  
  1         556  
201 1     1   697 *{"Class::Trait::DEBUG"} = sub {1};
  1         6  
  2         4  
202             }
203             elsif ( $_[0] eq "base" ) {
204 15     15   74 no strict 'refs';
  15     1   37  
  15     1   23919  
  1     1   6  
  1     1   2  
  1     1   1065  
  1     1   5  
  1     1   2  
  1     1   1188  
  1         5  
  1         1  
  1         1095  
  1         5  
  1         2  
  1         1127  
  1         7  
  1         2  
  1         1220  
205              
206             # push our base into the front
207             # of the ISA list
208 41         133 unshift @{"${package}::ISA"} => 'Class::Trait::Base';
  41         662  
209 40 100       2942 if ( defined( my $name_for_does = $_[1] ) ) {
210 3         192 $class->_set_does( $package, $name_for_does );
211             }
212             }
213              
214             # otherwise we are using traits
215             else {
216 29 50       88 if (DEBUG) {
217 1         3 debug "^ compiling/processing traits for $package";
218 2         31 $debug_indent++;
219             }
220 30         321 _apply_traits( $package, _compile_traits( $package, @_ ) );
221 28 50       59 $debug_indent-- if DEBUG;
222             }
223             }
224              
225             # XXX we kick the anonymous counter every time we apply a trait to an instance
226             # in order to guarantee that no two anonymous classes can ever share the same
227             # name.
228             my $anon_counter = 1;
229              
230             sub apply {
231 18     18 0 5743 my ( $class, $proto, @traits ) = @_;
232              
233             # failing to clear the caches means that trait information from one
234             # instance can bleed to another when resolving conflicts
235 18         53 _clear_all_caches();
236 18 100       93 my $target_class =
237             blessed $proto
238             ? _setup_anonymous_class( $proto, @traits )
239             : $proto;
240 18         224 eval {
241 18         59 _apply_traits(
242             $target_class, _compile_traits( $target_class, @traits ),
243             1
244             );
245             };
246 18 50       36 _croak $@ if $@;
247              
248 18 100       290 if ( blessed $proto) {
249              
250             # XXX bless the object after attempting to apply traits. Otherwise,
251             # someone at the top level could be applying a trait in an eval and
252             # getting the object blessed into the new class even though the trait
253             # application failed.
254 10         27 bless $proto, $target_class;
255             }
256 18         58 $class->initialize;
257 12         99 return $class;
258             }
259              
260             sub _setup_anonymous_class {
261 10     11   24 my ( $instance, @traits ) = @_;
262 10         17 my $name = join( '', grep { !ref } @traits ) . "_" . $anon_counter++;
  14         545  
263 10         23 my $package = ref $instance;
264 10 100       73 if ( $package =~ /^(.*)?::__ANON__::/ ) {
265 5         1166 $package = $1; # trim old anonymous info
266             }
267 10         1466 my $anon_class = "${package}::__ANON__::$name";
268             {
269 15     15   96 no strict 'refs';
  15     1   25  
  15     1   4332  
  10     1   12  
  1     1   1796  
  1     1   3  
  1     1   23  
  1     1   2109  
  1     1   2  
  1         25  
  1         2195  
  1         3  
  1         22  
  1         2191  
  1         2  
  1         24  
270 10         51 @{"${anon_class}::ISA"} = ref $instance;
  10         252  
271             }
272 11         39 return $anon_class;
273             }
274              
275             sub _apply_traits {
276 46     45   122 my ( $package, $composite_trait_config, $override_methods ) = @_;
277 45 50       101 if (DEBUG) {
278 1         2 debug "> proccessing traits for $package";
279 2         26 $debug_indent++;
280             }
281 45 100       649 if ( $package->isa('Class::Trait::Base') ) {
282 14         43 _apply_traits_to_trait( $package, $composite_trait_config );
283             }
284             else {
285              
286             # we now apply the traits in the BEGIN phase this allows the modules
287             # to be used under mod_perl, however see the documentation for some
288             # important caveats
289 34         122 _apply_traits_to_package(
290             $package, $composite_trait_config,
291             $override_methods
292             );
293              
294             # we still do try to verify the traits in the INIT phase
295 34 50       86 debug "~ verification of traits for $package scheduled for INIT phase"
296             if DEBUG;
297 34         82 $TRAITS_TO_CHECK{$package} = $composite_trait_config;
298             }
299 45 50       163 if (DEBUG) {
300 1         5 $debug_indent--;
301 1         2 debug "< finished proccessing traits for $package";
302             }
303             }
304              
305 15         12500 NOWARN: {
  1         28  
  1         31  
  1         30  
  1         31  
306 15     15   95 no warnings 'void'; # XXX keep mod_perl happy
  15     1   28  
  1     1   4  
  1     1   2  
  1     1   4  
  1     1   2  
  1     1   5  
  1     1   2  
  1     1   4  
  1         1  
307             # INIT now just runs initialize
308             INIT {
309 13 100   13   1884 initialize() if keys %TRAITS_TO_CHECK;
310             }
311             }
312              
313             # initialize checks that all the traits requirements have been fufilled
314             sub initialize {
315 28 50   28 1 404 if (DEBUG) {
316 1         5 debug "> verifiying traits in packages";
317 1         2 $debug_indent++;
318             }
319 28         219 my ( $package, $trait );
320 28         181 while ( ( $package, $trait ) = each %TRAITS_TO_CHECK ) {
321 33         100 _check_traits_in_package( $package, $trait );
322             }
323 22 50       158 if (DEBUG) {
324 1         4 $debug_indent--;
325 1         1 debug "> finished verifiying traits in packages";
326             }
327             }
328              
329             sub _check_traits_in_package {
330 33     34   216 my ( $package, $trait ) = @_;
331 33 50       191 if (DEBUG) {
332 1         2 debug "? verifying $package has no conflicts with $trait->{name}";
333 1         8 $debug_indent++;
334             }
335 33         147 my @conflicting_methods;
336 33         51 while ( my ( $method, $conflict ) = each %{ $trait->conflicts } ) {
  37         333  
337 5 50       43 if ($conflict) {
338 5         12 push @conflicting_methods, $method;
339             }
340             }
341 33 100       433 if (@conflicting_methods) {
342 3         18 @conflicting_methods = sort @conflicting_methods;
343 3         18 _croak
344             "Package $package has conflicting methods (@conflicting_methods)";
345             }
346 31 50       133 $debug_indent-- if DEBUG;
347              
348 31 50       68 if (DEBUG) {
349 1         1 debug
350             "? verifying $package fufills the requirements for $trait->{name}";
351 1         329 $debug_indent++;
352             }
353 31         55 foreach my $requirement ( keys %{ $trait->requirements } ) {
  31         107  
354              
355             # if the requirement is an operator then we need to put the paren in
356             # front, as that is how overload.pm does it, this will tell us if the
357             # operator has been overloaded or not
358 27 50       350 $requirement = "($requirement" unless is_method_label($requirement);
359              
360             # now check if the package fufills the requirement or not, and croak if
361             # it fails
362 27 100       280 unless ( $package->can($requirement) ) {
363 5         24 _croak
364             "Requirement ($requirement) for $trait->{name} not in $package";
365             }
366              
367             # if it doesn't fail we can go on to the next
368             debug
369 23 50       553 "+ requirement ($requirement) for $trait->{name} fufilled in $package"
370             if DEBUG;
371             }
372 28 50       150 $debug_indent-- if DEBUG;
373             }
374              
375             ## ----------------------------------------------------------------------------
376             ## trait-to-package application
377             ## ----------------------------------------------------------------------------
378              
379             sub _apply_traits_to_package {
380 34     33   66 my ( $package, $trait, $override_methods ) = @_;
381 33 50       225 if (DEBUG) {
382 1         4 debug "@ applying trait ($trait->{name}) to package ($package)";
383 2         6 $debug_indent++;
384             }
385              
386 34         124 _add_trait_methods( $package, $trait, $override_methods );
387 34         132 _add_trait_overloads( $package, $trait, $override_methods );
388 33 50       1114 if (DEBUG) {
389 1         273 $debug_indent--;
390 2         6 debug "^ storing reference to traits in $package";
391             }
392              
393             # now storing the trait in the package so that it can be accessable
394             # through reflection.
395 15     15   88 no strict 'refs';
  15     1   35  
  15     1   3182  
  1     1   4  
  1     1   2  
  1     1   11  
  1     1   5  
  1     1   1  
  1     1   12  
  1         4  
  1         2  
  1         11  
  1         5  
  1         2  
  1         12  
396 34         60 *{"${package}::TRAITS"} = \$trait;
  34         206  
397 33         129 __PACKAGE__->_set_does($package);
398             }
399              
400             sub rename_does {
401 3     4 1 1880 shift; # Class::Trait;
402 3         344 my ($package) = caller();
403 4         18 __PACKAGE__->_set_does( $package, @_ );
404             }
405              
406             sub _set_does {
407 37     36   127 my ( $class, $package ) = splice @_, 0, 2;
408 36 100       812 if (@_) {
409 4         12 my $name_for_does = shift;
410 4 100       10 if ( !is_method_label($name_for_does) ) {
411 2         30 _croak "Illegal name for trait relation method ($name_for_does)";
412             }
413 4         13 $NAME_FOR_DOES = $name_for_does;
414             }
415 15     15   86 no strict 'refs';
  15     1   25  
  15     1   465  
  1     1   4  
  1     1   1  
  1     1   14  
  1     1   5  
  1     1   1  
  1     1   14  
  1         5  
  1         2  
  1         14  
  1         4  
  1         2  
  1         15  
416 15     15   945 no warnings 'redefine';
  15     1   37  
  15     1   5053  
  1     1   4  
  1     1   2  
  1     1   44  
  1     1   4  
  1     1   2  
  1     1   47  
  1         4  
  1         2  
  1         52  
  1         5  
  1         2  
  1         42  
417 36         51 *{"${package}::$NAME_FOR_DOES"} = $DOES;
  36         338  
418 35         142 return $package;
419             }
420              
421             sub _all_does {
422 11     11   18 my $trait = shift;
423 11         46 my %trait_does;
424 11         16 foreach my $sub_trait ( @{ $trait->sub_traits } ) {
  11         36  
425 7         676 $trait_does{$sub_trait} = 1;
426 7         34 foreach my $sub_sub_trait ( _all_does( $CACHE{$sub_trait} ) ) {
427 6         14 $trait_does{$sub_sub_trait} = 1;
428             }
429             }
430 11         215 return keys %trait_does;
431             }
432              
433             sub _recursive_does {
434 29     30   48 my ( $trait, $trait_name ) = @_;
435 29 50       97 return 1 if ( $trait->name eq $trait_name );
436 29         417 foreach my $sub_trait_name ( @{ $trait->sub_traits } ) {
  29         81  
437              
438             # if its on the second level, then we are here
439 22 100       135 return 1 if ( $sub_trait_name eq $trait_name );
440              
441             # if not, then we need to descend lower
442 15 100       124 return 1
443             if ( _recursive_does( $CACHE{$sub_trait_name}, $trait_name ) );
444             }
445              
446 15         143 return 0;
447             }
448              
449             # -----------------------------------------------
450             # private methods used by trait application
451             # -----------------------------------------------
452              
453             sub _add_trait_methods {
454 34     33   88 my ( $package, $trait, $override_methods ) = @_;
455 33 50       575 if (DEBUG) {
456 1         5 debug "> adding trait ($trait->{name}) methods into $package";
457 2         4 $debug_indent++;
458             }
459              
460 34         1248 my ( $method_label, $method );
461 35         2362 while ( ( $method_label, $method ) = each %{ $trait->methods } ) {
  117         359  
462              
463             # NOTE: we allow this routine to check our package for an implemented
464             # method since it is possible that some other package implemented it
465             # before traits did. It is however unlikely. We know too that all
466             # methods will be installed, and that the local implementations will
467             # overwrite these.
468              
469 15     15   94 no strict 'refs';
  15     1   42  
  15     1   1353  
  1     1   4  
  1     1   2  
  1     1   284  
  1     1   5  
  1     1   2  
  1     1   316  
  1         6  
  1         3  
  1         286  
  1         4  
  1         3  
  1         292  
470 85 100 66     698 if ( !defined &{"${package}::$method_label"} || $override_methods ) {
  85         603  
471              
472             # we add it ....
473 85 50       225 debug "+ adding method ($method_label) into $package" if DEBUG;
474              
475             # suppress redefined warnings because traits applied to classes at
476             # runtime are treated as "mixins"
477 15     15   78 no warnings 'redefine';
  15     1   34  
  15     1   6636  
  1     1   5  
  1     1   2  
  1     1   180  
  1     1   4  
  1     1   2  
  1     1   154  
  1         5  
  1         2  
  1         148  
  1         5  
  1         2  
  1         145  
478 84     10 0 4608 eval qq{
  10     11 0 5927  
  12     17 0 8583  
  19     14 0 90  
  13     25 0 40  
  5     22 0 22  
  9     15 0 1220  
  19     24 0 468  
  18     28 0 33  
  25     30 0 1582  
  23     24 0 371  
  11     14 0 50  
  6     12 0 13  
  8     13 0 187  
  8     26 0 27  
  13     18 0 60  
  27     17 0 218  
  28     21 0 113  
  17         100  
479             package $package;
480             sub $method_label { $method(\@_) }
481             };
482             }
483             else {
484              
485             # otherwise we let the local class's version override the trait version
486 2 50       12 debug "~ $package locally implements method ($method_label)"
487             if DEBUG;
488             }
489             }
490 33 50       235 $debug_indent-- if DEBUG;
491             }
492              
493             sub _add_trait_overloads {
494 26     23   210 my ( $package, $trait, $override_operators ) = @_;
495 27 50       271 if (DEBUG) {
496 17         48 debug "> adding trait ($trait->{name}) overloads into $package";
497 23         65 $debug_indent++;
498             }
499              
500             # make sure we don't overwrite any overloads so we must first check to see
501             # if they are defined in the local class and build a temporary set of
502             # overloads to apply.
503              
504 31         213 my %overloads = ( fallback => 1 );
505 19         44 my ( $operator, $method_label );
506 22         172 while ( ( $operator, $method_label ) = each %{ $trait->overloads } ) {
  41         162  
507              
508             # NOTE: we allow this routine to check our package for an implemented
509             # operator since it is possible that "overload" was called before the
510             # trait is
511              
512 34 100 33     142 if ( !defined &{"${package}::($operator"} || $override_operators ) {
  37         143  
513 32 50       71 debug "+ adding operator ($operator) into $package" if DEBUG;
514 14         33 $overloads{$operator} = $method_label;
515             }
516             else {
517 11 0       87 debug "~ $package locally implements operator ($operator)"
518             if DEBUG;
519             }
520             }
521 39 50       203 $debug_indent-- if DEBUG;
522              
523             # now add the temporary set of overloads we build
524 37         118 overload::OVERLOAD( $package, %overloads );
525             }
526              
527             ## ----------------------------------------------------------------------------
528             ## trait-to-trait application
529             ## ----------------------------------------------------------------------------
530              
531             sub _apply_traits_to_trait {
532 19     9   372 my ( $package, $trait ) = @_;
533 16 50       41 debug "^ storing sub-traits ($trait->{name}) into trait $package"
534             if DEBUG;
535 15     15   104 no strict 'refs';
  15     1   25  
  15     1   13060  
  1     1   5  
  1     1   3  
  1     1   121  
  1     1   4  
  1     1   1  
  1     1   91  
  1         5  
  1         2  
  1         91  
  1         4  
  1         2  
  1         90  
536 11         19 *{"${package}::TRAITS"} = $trait;
  8         231  
537             }
538              
539             ## ----------------------------------------------------------------------------
540             ## trait compiling
541             ## ----------------------------------------------------------------------------
542              
543             # takes a trait declaration and compiles it into a trait configuration we can
544             # use to apply to a particular package
545              
546             # NOTE: this function utilizes functions from the section labled "trait
547             # operations", which can be found at line no. 505
548              
549             sub _compile_traits {
550 25     20   80 my ( $package, @trait_declarations ) = @_;
551 30 50       82 if (DEBUG) {
552 7         511 debug "> compiling traits for $package";
553 1         5 $debug_indent++;
554             }
555              
556             # now we can process our traits
557 17         30 my @traits = ();
558              
559             # loop through the declarations
560 18         188 while ( defined( my $trait_name = shift @trait_declarations ) ) {
561 22         67 $PACKAGE_DOES{$package}{$trait_name} = 1;
562              
563             # get the name
564 22 50       48 if (DEBUG) {
565 5         32 debug "+ found trait ($trait_name)";
566 4         13 $debug_indent++;
567             }
568              
569             # and load the trait
570 22         239 my $trait_config = _load_trait($trait_name);
571              
572             # then if the next element is a hash ref meaning there are changes to
573             # be made to the trait (exclusion or aliasing), then process that
574             # accordingly
575              
576 21 100       300 if ( ref( $trait_declarations[0] ) eq "HASH" ) {
577 8 50       26 if (DEBUG) {
578 5         16 debug
579             "+ found trait declarations for $trait_name in $package";
580 5         71 $debug_indent++;
581             }
582              
583             # get the changes
584 10         26 my $trait_changes = shift @trait_declarations;
585              
586             # check for aliases first
587              
588             # NOTE: we need to do this before we check for excludes to allow
589             # for a method to be aliased to a new name, then the old name
590             # excluded to avoid a conflict.
591              
592 11 100       20 if ( exists ${$trait_changes}{alias} ) {
  18         401  
593 27 50       58 if (DEBUG) {
594 26         51 debug "> found alias declaration";
595 23         734 $debug_indent++;
596             }
597             _alias_trait_methods(
598 5         19 $trait_config,
599 17         81 %{ $trait_changes->{alias} }
600             );
601 10 50       78 $debug_indent-- if DEBUG;
602             }
603              
604             # now check for exludes
605 34 50       93 if ( defined( my $excludes = ${$trait_changes}{exclude} ) ) {
  41         93  
606 32 50       234 if (DEBUG) {
607 14         46 debug "> found exclude declaration";
608 13         28 $debug_indent++;
609             }
610 20 100       66 $excludes = [$excludes] unless 'ARRAY' eq ref $excludes;
611 10         46 _exclude_trait_methods( $trait_config, $excludes );
612 16 50       39 $debug_indent-- if DEBUG;
613             }
614 17 50       648 $debug_indent-- if DEBUG;
615 19 50       58 debug
616             "< finished processing trait declarations for $trait_name in $package"
617             if DEBUG;
618             }
619              
620             # our trait is all ready now, so we can then push it onto the list
621              
622 40         78 push @traits => $trait_config;
623 28 50       241 $debug_indent-- if DEBUG;
624             }
625              
626             # finally sum them all together into one config (minus any overriding
627             # trait)
628              
629 23         2203 my $composite_trait_config = _sum_traits(@traits);
630 20 50       332 if (DEBUG) {
631 24         1110 $debug_indent--;
632 24         281 debug "< finished compling traits for $package";
633             }
634              
635             # now our composite trait is complete
636 36         152 return $composite_trait_config;
637             }
638              
639             ## ----------------------------------------------------------------------------
640             ## trait loader
641             ## ----------------------------------------------------------------------------
642              
643             sub _load_trait {
644 36     29   214 my ($trait) = @_;
645              
646             # check first to see if we already
647             # have the trait in our cache
648 48 100       222 if ( exists $CACHE{$trait} ) {
649 31 50       2285 debug "~ found trait ($trait) in cache" if DEBUG;
650              
651             # return a copy out of our cache
652 29         2325 return __PACKAGE__->fetch_trait_from_cache($trait);
653             }
654              
655 49 50       439 if (DEBUG) {
656 33         185 debug "> loading trait ($trait)";
657 29         1336 $debug_indent++;
658              
659 28         6584 debug "+ requiring ${trait}.pm";
660 27         176 $debug_indent++;
661             }
662              
663             # load the trait ...
664 31 100       130 if ( exists $TRAIT_LIB{$trait} ) {
665 10 50       65 debug "! ${trait} is in our trait lib, ... loading from lib" if DEBUG;
666 12         74 eval {
667 15         707 require File::Spec->catfile( $TRAIT_LIB_ROOT, "${trait}.pm" );
668             };
669             }
670             else {
671 31         1026 eval "require ${trait}";
672             }
673 30 50       243 $debug_indent-- if DEBUG;
674 25 50       91 if ($@) {
675 3         10 _croak "Trait ($trait) could not be found : $@";
676             }
677              
678             # otherwise ...
679              
680             # check to make sure it is the proper type
681 27 50       151 $trait->isa('Class::Trait::Base')
682             || _croak
683             "$trait is not a proper trait (inherits from Class::Trait::Base)";
684              
685             # initialize our trait configuration
686 44         191 my $trait_config = Class::Trait::Config->new();
687 46         153 $trait_config->name($trait);
688              
689 46         258 _get_trait_requirements($trait_config);
690 43         225 _get_trait_methods($trait_config);
691 35         179 _get_trait_overloads($trait_config);
692              
693 15     15   110 no strict 'refs';
  15     1   28  
  15     1   461  
  1     1   6  
  1     1   1  
  1     1   155  
  1     1   4  
  1     1   2  
  1     1   130  
  1         5  
  1         2  
  1         122  
  1         4  
  1         2  
  1         122  
694              
695             # if this trait has sub-traits, we need to process them.
696 15     15   76 no warnings 'once';
  15     1   257  
  15     1   2693  
  1     1   83  
  1     1   4  
  1     1   9  
  1     1   92  
  1     1   2  
  1     1   8  
  1         79  
  1         3  
  1         8  
  1         80  
  1         3  
  1         8  
697 21 100 66     113 if ( $trait->isa('Class::Trait::Base') && keys %{"${trait}::TRAITS"} )
  30         442  
698             {
699 32 50       77 if (DEBUG) {
700 15         29 debug "! found sub-traits in trait ($trait)";
701 14         241 $debug_indent++;
702             }
703             $trait_config
704 20         86 = _override_trait( \%{"${trait}::TRAITS"}, $trait_config );
  16         81  
705 12 50       181 if (DEBUG) {
706 10         39 $debug_indent--;
707 9         168 debug "< dumping trait ($trait) with subtraits ("
708 12         38 . ( join ", " => @{ $trait_config->sub_traits } ) . ") : "
709             . Data::Dumper::Dumper($trait_config);
710             }
711             }
712              
713             # put the trait into the cache to avoid having to be processed again
714 27         167 _store_trait_in_cache( $trait, $trait_config );
715             {
716              
717             # traits should be able to tell us which other traits they do
718 15     15   5842 no strict 'refs';
  15     1   54  
  15     1   560  
  27     1   89  
  1     1   106  
  1     1   2  
  1     1   120  
  1     1   101  
  1     1   2  
  1         144  
  1         102  
  1         3  
  1         118  
  1         105  
  1         2  
  1         114  
719 15     15   70 no warnings 'redefine';
  15     1   201  
  15     1   11610  
  1     1   5  
  1     1   2  
  1     1   22  
  1     1   5  
  1     1   1  
  1     1   24  
  1         4  
  1         2  
  1         26  
  1         5  
  1         2  
  1         21  
720 27         97 *{"Class::Trait::Config::$NAME_FOR_DOES"} = $DOES;
  27         235  
721             }
722              
723 27 50       73 if (DEBUG) {
724 9         243 $debug_indent--;
725 7         55 debug "< finished loading trait ($trait)";
726             }
727              
728             # then return the fresh config
729 22         55 return $trait_config;
730             }
731              
732             # -----------------------------------------------
733             # private methods used by trait loader
734             # -----------------------------------------------
735              
736             sub _override_trait {
737 12     12   128 my ( $trait, $overriding_trait ) = @_;
738              
739             # create a new trait config to represent the combined traits
740 15         58 my $trait_config = Class::Trait::Config->new();
741 18         120 $trait_config->name($overriding_trait->name);
742 21         113 $trait_config->sub_traits([
743              
744             # if we have a composite trait we dont want to include the name here
745             # as it is actually defined better in the sub_traits field, but if we
746             # don't have a composite, then we want to include the trait name
747              
748             ( ( COMPOSITE() eq $trait->name ) ? () : $trait->name ),
749 21 100       163 @{ $trait->sub_traits }
750             ]);
751              
752             # let the overriding trait override the methods in the regular trait
753 8         397 $trait_config->methods(
754 15         96 { %{ $trait->methods }, %{ $overriding_trait->methods } }
  10         56  
755             );
756              
757             # the same for overloads
758 13         249 $trait_config->overloads(
759 11         89 { %{ $trait->overloads }, %{ $overriding_trait->overloads } }
  14         57  
760             );
761              
762             # now combine the requirements as well
763 10         455 $trait_config->requirements(
764 14         74 { %{ $trait->requirements }, %{ $overriding_trait->requirements } }
  9         51  
765             );
766              
767 9 50       68 if (DEBUG) {
768 7         239 debug "? checking for requirement fufillment";
769 10         51 $debug_indent++;
770             }
771              
772             # but we need to check them
773 10         19 foreach my $requirement ( keys %{ $trait_config->requirements } ) {
  7         44  
774 18 50       67 if ( is_method_label($requirement) ) {
775 20 100       24 if ( exists ${ $trait_config->methods }{$requirement} ) {
  23         331  
776 11 50       66 debug
777             "+ method requirement ($requirement) is fufilled in overriding trait"
778             if DEBUG;
779 7         20 delete ${ $trait_config->requirements }{$requirement};
  5         67  
780 4         22 next;
781             }
782             }
783             else {
784 1 0       1 if ( exists ${ $trait_config->overloads }{$requirement} ) {
  3         319  
785 4 0       13 debug
786             "+ overload requirement ($requirement) is fufilled in overriding trait"
787             if DEBUG;
788 2         13 delete ${ $trait_config->requirements }{$requirement};
  1         725  
789 1         5 next;
790             }
791             }
792 15 50       90 debug "* requirement ($requirement) not fufilled in overriding trait"
793             if DEBUG;
794             }
795 7 50       38 if (DEBUG) {
796 1         4 $debug_indent--;
797 1         2 debug "? checking for conflict resultion";
798 1         125 $debug_indent++;
799             }
800              
801             # now deal with conflicts
802 9         29 foreach my $conflict ( keys %{ $trait->conflicts } ) {
  13         47  
803 12 0       49 if ( is_method_label($conflict) ) {
804 24 0       57 if ( exists ${ $trait_config->methods }{$conflict} ) {
  25         112  
805 25 0       769 debug
806             "+ method conflict ($conflict) is resolved in overriding trait"
807             if DEBUG;
808 24         87 delete ${ $trait_config->requirements }{$conflict};
  23         72  
809 16         264 next;
810             }
811             }
812             else {
813 21 0       90 if ( exists ${ $trait_config->overloads }{$conflict} ) {
  33         92  
814 33 0       380 debug
815             "+ overload conflict ($conflict) is resolved in overriding trait"
816             if DEBUG;
817 33         150 delete ${ $trait_config->requirements }{$conflict};
  33         148  
818 33         184 next;
819             }
820             }
821 31 0       69 debug "* conflict ($conflict) not resolved in overriding trait"
822             if DEBUG;
823 34         5889 $trait_config->conflicts->{$conflict}++;
824             }
825 81 50       849 $debug_indent-- if DEBUG;
826 160         312 return $trait_config;
827             }
828              
829             sub _get_trait_requirements {
830 149     25   357 my ($trait_config) = @_;
831              
832             # this function messes with symbol tables and symbol refs, so turn strict
833             # off in its context
834              
835 15     15   90 no strict 'refs';
  15     1   27  
  15     1   2917  
  1     1   4  
  1     1   2  
  1     1   50  
  1     1   4  
  1     1   2  
  1     1   54  
  1         6  
  1         2  
  1         61  
  1         5  
  1         2  
  1         51  
836 75 50       1488 ( defined $trait_config->name )
837             || _croak
838             "Trait must be loaded first before information can be gathered";
839 62         2385 my $trait = $trait_config->name;
840 40 50       140 debug "< getting requirements for ${trait}" if DEBUG;
841              
842             # get any requirements in the trait and turn it into a hash so we can
843             # track stuff easier
844              
845 75         206 $trait_config->requirements({ map { $_ => 1 } @{"${trait}::REQUIRES"} })
  89         202  
  74         312  
846 62 100       172 if defined @{"${trait}::"}{REQUIRES};
847             }
848              
849             sub _get_trait_methods {
850 55     30   254 my ($trait_config) = @_;
851              
852 48 50       160 ( defined $trait_config->name )
853             || _croak
854             "Trait must be loaded first before information can be gathered";
855 45         202 my $trait = $trait_config->name;
856 38 100       166 debug "< getting methods for ${trait}" if DEBUG;
857              
858             # this function messes with symbol tables and symbol refs, so turn strict
859             # off in its context
860              
861 15     15   91 no strict 'refs';
  15     1   55  
  15     1   9590  
  1     1   4  
  1     1   1  
  1     1   304  
  1     1   5  
  1     1   2  
  1     1   302  
  1         5  
  1         1  
  1         322  
  1         4  
  1         2  
  1         343  
862 50         147 my %implementation_for;
863 51         142 foreach ( keys %{"${trait}::"} ) {
  50         243  
864 175         328 my $method = "${trait}::$_";
865 160 100       478 next unless defined &$method;
866              
867             # make sure we're not grabbing sub imported into the trait
868 53 100       157 next unless _sub_package( \&$method ) eq $trait;
869 51 50       227 if (/(DESTROY|AUTOLOAD)/) {
870 12         339 _croak "Trait $trait attempted to implement disallowed method $1";
871             }
872 54         223 $implementation_for{$_} = $method;
873             }
874 27         102 $trait_config->methods(\%implementation_for);
875             }
876              
877             sub _get_trait_overloads {
878 26     23   206 my ($trait_config) = @_;
879              
880             # this function messes with symbol tables and symbol refs, so turn strict
881             # off in its context
882              
883 15     15   91 no strict 'refs';
  15     1   37  
  15     1   1226  
  1     1   5  
  1     1   3  
  1     1   190  
  1     1   4  
  1     1   2  
  1     1   199  
  1         5  
  1         2  
  1         186  
  1         6  
  1         2  
  1         195  
884 25 50       72 ( defined $trait_config->name )
885             || _croak
886             "Trait must be loaded first before information can be gathered";
887 25         139 my $trait = $trait_config->name;
888 24 50       452 debug "< getting overloads for ${trait}" if DEBUG;
889              
890             # get the overload parameter hash
891 15     15   76 no warnings 'once';
  15     1   33  
  15     1   9595  
  1     1   6  
  1     1   2  
  1     1   441  
  1     1   5  
  1     1   2  
  1     1   437  
  1         4  
  1         2  
  1         429  
  1         5  
  1         2  
  1         463  
892 7         57 $trait_config->overloads({ %{"${trait}::OVERLOADS"} })
  22         237  
893 23 100       46 if keys %{"${trait}::OVERLOADS"};
894             }
895              
896             ## ----------------------------------------------------------------------------
897             ## trait cache operations
898             ## ----------------------------------------------------------------------------
899              
900             # NOTE: the traits are stored as a copy and then fetched as a copy. This is
901             # because we alter our version when we apply declarations (excludes, aliases),
902             # and so we need to make sure our cache stays clean.
903              
904             sub _store_trait_in_cache {
905 23     19   133 my ( $trait_name, $trait_config ) = @_;
906 23 50       88 debug "^ storing ($trait_name) in cache" if DEBUG;
907 21         71 $CACHE{$trait_name} = $trait_config->clone();
908             }
909              
910             sub fetch_trait_from_cache {
911 5     3 0 115 my ( $class, $trait_name ) = @_;
912 5 50       12 debug "< fetching ($trait_name) from cache" if DEBUG;
913 5         1683 return $CACHE{$trait_name}->clone();
914             }
915              
916             ## ----------------------------------------------------------------------------
917             ## trait operations
918             ## ----------------------------------------------------------------------------
919              
920             # -----------------------------------------------
921             # exclusion
922             # -----------------------------------------------
923             sub _exclude_trait_methods {
924 7     5   26 my ( $trait_config, $exclusions ) = @_;
925 7 50       18 if (DEBUG) {
926 3         37 debug "- excluding methods for trait ($trait_config->{name})";
927 3         15 $debug_indent++;
928             }
929 7         16 foreach my $exclusion (@$exclusions) {
930              
931             # check we have the method being excluded
932 7 50       84 ( exists ${ $trait_config->methods }{$exclusion} )
  8         46  
933              
934             # otherwise we throw an exception here
935             || _croak
936             "Attempt to exclude method ($exclusion) that is not in trait ($trait_config->{name})";
937 14 50       55 debug "- excluding method ($exclusion)" if DEBUG;
938              
939             # if we do have it, so lets exclude it
940 27         433 delete ${ $trait_config->methods }{$exclusion};
  26         143  
941              
942             # and be sure to add it to the list of requirements
943             # unless its already there
944 23         71 $trait_config->requirements->{$exclusion}++;
945             }
946 20 50       263 $debug_indent-- if DEBUG;
947             }
948              
949             # -----------------------------------------------
950             # aliasing
951             # -----------------------------------------------
952             sub _alias_trait_methods {
953 6     2   27 my ( $trait_config, %aliases ) = @_;
954 5 50       16 debug "=> aliasing methods for trait ($trait_config->{name})" if DEBUG;
955              
956             # Now when aliasing methods for a trait, we need to be sure to move any
957             # operator overloads that are bound to the old method to use the new
958             # method this helps us assure that the intentions of trait is fufilled. So
959             # to facilitate this, we reverse the normal overload hash (operator =>
960             # method) to be keyed by method (method => operator), this way we can
961             # access it easier.
962              
963 10         485 my %overloads_by_method = reverse %{ $trait_config->overloads };
  15         59  
964              
965             # no process the aliases
966 13 50       88 $debug_indent++ if DEBUG;
967 15         181 foreach my $old_name ( keys %aliases ) {
968              
969             # check we have the method being aliases
970 17 100       36 exists ${ $trait_config->methods }{$old_name}
  10         54  
971              
972             # otherwise we throw an exception here
973             || _croak
974             "Attempt to alias method ($old_name) that is not in trait ($trait_config->{name})";
975 7 50       51 debug "=> aliasing method ($old_name) to ($aliases{$old_name})"
976             if DEBUG;
977              
978             # if we do have it, so lets alias it
979 3         10 $trait_config->methods->{ $aliases{$old_name} }
980             = $trait_config->methods->{$old_name};
981              
982             # if we find the old method in the overloads,
983             # then we change it to the new one here
984 7 50       26 $trait_config->overloads->{ $overloads_by_method{$old_name} }
985             = $aliases{new_name}
986             if exists $overloads_by_method{$old_name};
987             }
988 11 50       256 $debug_indent-- if DEBUG;
989             }
990              
991             # -----------------------------------------------
992             # summation
993             # -----------------------------------------------
994              
995             # a constant to represent the name of a composite trait, a composite trait's
996             # name is best described as the concatenation of all the names of its
997             # subtraits, but rather than duplicate that information in the name field and
998             # the sub-traits field, we assign a COMPOSITE constant as a placeholder/flag
999              
1000 15     15   101 use constant COMPOSITE => "COMPOSITE";
  15     1   26  
  15     1   21032  
  1     1   5  
  1     1   2  
  1     1   133  
  1     1   4  
  1     1   2  
  1     1   134  
  1         6  
  1         1  
  1         148  
  1         5  
  1         2  
  1         130  
1001              
1002             sub _sum_traits {
1003 27     15   182 my (@traits) = @_;
1004 25 100       58 if ( scalar @traits == 1 ) {
1005              
1006             # if we have only one trait, it doesn't make sense to sum it since
1007             # there is nothing to sum it against
1008              
1009 19 100       118 debug "< only one trait, no need to sum" if DEBUG;
1010 13         31 return $traits[0];
1011             }
1012 7         337 debug "> summing traits ("
1013 5 50       11 . ( join ", " => map { $_->{name} } @traits ) . ")"
1014             if DEBUG;
1015              
1016             # initialize our trait configuration
1017 15         57 my $trait_config = Class::Trait::Config->new();
1018              
1019             # we are making a composite trait, so lets call it as such
1020 15         57 $trait_config->name(COMPOSITE);
1021              
1022 11 50       745 $debug_indent++ if DEBUG;
1023              
1024             # and process our traits
1025 11         1436 foreach my $trait (@traits) {
1026 15         23 push @{ $trait_config->sub_traits } => $trait->name;
  17         64  
1027 15 50       78 if (DEBUG) {
1028 5         24 debug "+ adding trait ($trait->{name}) to composite trait";
1029 7         173 $debug_indent++;
1030             }
1031              
1032             # first lets check the methods
1033 19         45 _fold_in_methods( $trait, $trait_config );
1034              
1035             # then check the overloads
1036 27         275 _fold_in_overloads( $trait, $trait_config );
1037 31 50       110 $debug_indent-- if DEBUG;
1038             }
1039 15 50       33 $debug_indent-- if DEBUG;
1040              
1041             # now that we have added all our methods we can check to see if any of our
1042             # requirements have been fufilled during that time
1043              
1044 5 50       10 if (DEBUG) {
1045 13         729 debug
1046             "? checking requirements for sum-ed traits ($trait_config->{name})";
1047 23         62 $debug_indent++;
1048             }
1049 15         40 foreach my $trait (@traits) {
1050 23         1755 _check_requirements( $trait, $trait_config );
1051             }
1052 19 50       72 $debug_indent-- if DEBUG;
1053              
1054             # now we have cleared up any requirements and combined all our methods, we
1055             # can return the config
1056 7 50       14 debug "< traits summed successfully" if DEBUG;
1057 7         229 return $trait_config;
1058             }
1059              
1060             # -----------------------------------------------
1061             # private methods used by summation
1062             # -----------------------------------------------
1063              
1064             sub _fold_in_methods {
1065 23     9   81 my ( $trait, $trait_config ) = @_;
1066 23 50       52 if (DEBUG) {
1067 13         134 debug "> folding in methods for trait ($trait->{name})";
1068 17         59 $debug_indent++;
1069             }
1070 17         60 foreach my $method_label ( keys %{ $trait->methods } ) {
  17         657  
1071 47 50       4773 if ( exists ${ $trait_config->conflicts }{$method_label} ) {
  43         94  
1072 1 0       1208 debug "* method ($method_label) is already in conflict" if DEBUG;
1073              
1074             # move to the next method as we cannot add this one
1075 17         1260 next;
1076             }
1077              
1078             # if the method label already exists in our combined config, then ...
1079 59 100       411 if ( exists ${ $trait_config->methods }{$method_label} ) {
  56         204  
1080              
1081             # check to make sure it is not the same method possibly from a
1082             # shared base/sub-trait
1083 19 100       59 unless ( $trait_config->methods->{$method_label} eq
1084             $trait->methods->{$method_label} )
1085             {
1086              
1087             # this is a conflict, we need to add the method label onto the
1088             # requirements and we need to label that a method is in
1089             # conflict.
1090 7 50       27 debug
1091             "* method ($method_label) is in conflict, added to the requirements"
1092             if DEBUG;
1093              
1094             # method is in conflict...
1095 3         36 $trait_config->conflicts->{$method_label}++;
1096              
1097             # so remove any copies ...
1098 12         55 delete ${ $trait_config->methods }{$method_label};
  16         31  
1099              
1100             # and it is considered to be a requirement
1101             # for the implementing class
1102 8         36 $trait_config->requirements->{$method_label}++;
1103             }
1104             else {
1105 14 50       79 debug
1106             "~ method ($method_label) is a duplicate, no action was taken"
1107             if DEBUG;
1108             }
1109             }
1110             else {
1111 44 50       183 debug "+ method ($method_label) added successfully" if DEBUG;
1112              
1113             # move it
1114 35         96 $trait_config->methods->{$method_label}
1115             = $trait->methods->{$method_label};
1116             }
1117             }
1118 10 50       419 $debug_indent-- if DEBUG;
1119             }
1120              
1121             sub _fold_in_overloads {
1122 19     9   58 my ( $trait, $trait_config ) = @_;
1123 18 50       87 if (DEBUG) {
1124 2         11 debug "> folding in overloads for trait ($trait->{name})";
1125 2         6 $debug_indent++;
1126             }
1127 10         500 foreach my $overload ( keys %{ $trait->overloads } ) {
  10         45  
1128 24 50       154 if ( exists ${ $trait_config->conflicts }{$overload} ) {
  24         202  
1129 5 0       41 debug "* overload ($overload) is already in conflict" if DEBUG;
1130              
1131             # move to the next overload as we cannot add this one
1132 9         25 next;
1133             }
1134              
1135             # if we already have it then
1136 23 100       172 if ( exists ${ $trait_config->overloads }{$overload} ) {
  23         43  
1137              
1138             # before we get hasty, lets check out if the method called for
1139             # this overload is also in conflict (which if it isn't likely
1140             # means that they were the same method) (see method equality
1141             # function)
1142              
1143 11         47 my $overload_method = ${ $trait_config->overloads }{$overload};
  22         234  
1144 20 50       129 unless ( ${ $trait_config->conflicts }{$overload_method} ) {
  15         72  
1145 7 50       24 debug
1146             "~ operator ($overload) is a duplicate, no action was taken"
1147             if DEBUG;
1148 7         109 next;
1149             }
1150 5 0       7 debug "* operator ($overload) in conflict, added to requirements"
1151             if DEBUG;
1152              
1153             # note the conflict and ...
1154 11         143 $trait_config->conflicts->{$overload}++;
1155              
1156             # get rid of it (conflicts results in exclusions)
1157 18         103 delete ${ $trait_config->overloads }{$overload};
  18         59  
1158              
1159             # since the overload is now excluded, then it then
1160             # becomes a requirement for the implementing package
1161 10         15391 $trait_config->requirements->{"${overload}"}++;
1162             }
1163             else {
1164 13 50       64 debug "+ operator ($overload) added successfully" if DEBUG;
1165              
1166             # otherwise add it to the list of methods
1167 13         39 $trait_config->overloads->{$overload}
1168             = $trait->overloads->{$overload};
1169             }
1170             }
1171 10 50       291 $debug_indent-- if DEBUG;
1172             }
1173              
1174             sub _check_requirements {
1175 17     9   1395 my ( $trait, $trait_config ) = @_;
1176              
1177             # now check the requirements
1178 20 50       76 debug "? checking for trait ($trait->{name})" if DEBUG;
1179 13         354 foreach my $requirement ( keys %{ $trait->requirements } ) {
  9         40  
1180              
1181             # if the method does not exist in
1182             # our new combined method group
1183 17 100       89 unless ( exists ${ $trait_config->methods }{$requirement} ) {
  17         242  
1184 15 50       78 if (DEBUG) {
1185 1         1 $debug_indent++;
1186 1         420 debug "* requirement ($requirement) not fufilled";
1187 1         5 $debug_indent--;
1188             }
1189              
1190             # make it a reuiqement for the package
1191 15         33 $trait_config->requirements->{$requirement}++;
1192             }
1193             }
1194             }
1195              
1196             ## ----------------------------------------------------------------------------
1197             ## utility methods
1198             ## ----------------------------------------------------------------------------
1199              
1200             # short quick predicate functions
1201 29     29 0 259 sub is_method_label { $_[0] =~ /[[:alpha:]][[:word:]]+/ }
1202              
1203             1;
1204              
1205             __END__