File Coverage

lib/UR/AttributeHandlers.pm
Criterion Covered Total %
statement 42 57 73.6
branch 9 12 75.0
condition 4 11 36.3
subroutine 11 14 78.5
pod 0 7 0.0
total 66 101 65.3


line stmt bran cond sub pod time code
1             package UR::AttributeHandlers;
2              
3 266     266   981 use strict;
  266         337  
  266         5946  
4 266     266   841 use warnings;
  266         305  
  266         4881  
5 266     266   126496 use attributes;
  266         261880  
  266         1231  
6              
7             our @CARP_NOT = qw(UR::Namespace);
8              
9             our $VERSION = "0.46"; # UR $VERSION;;
10              
11             # implement's UR's mechanism for sub/variable attributes.
12             my %support_functions = (
13             MODIFY_CODE_ATTRIBUTES => \&modify_attributes,
14             FETCH_CODE_ATTRIBUTES => \&fetch_attributes,
15             MODIFY_SCALAR_ATTRIBUTES => \&modify_attributes,
16             );
17              
18             sub import_support_functions_to_package {
19 462     462 0 925 my $package = shift;
20              
21 462         2539 while( my($name, $code) = each %support_functions ) {
22 1386         2365 my $target = join('::', $package, $name);
23 1386         1196 do {
24 266     266   30885 no strict 'refs';
  266         430  
  266         151203  
25 1386         175480 *$target = $code;
26             };
27             }
28             }
29              
30              
31             my %modify_attribute_handlers = (
32             CODE => { Overrides => \&modify_code_overrides },
33             SCALAR => { RoleParam => \&modify_scalar_role_property },
34             );
35             my %fetch_attribute_handlers = (
36             CODE => { Overrides => \&fetch_code_overrides },
37             );
38              
39             sub _modify_attribute_handler {
40 8     8   8 my($ref, $attr) = @_;
41 8         16 my $reftype = attributes::reftype($ref);
42 8   33     35 return (exists($modify_attribute_handlers{$reftype}) and $modify_attribute_handlers{$reftype}->{$attr});
43             }
44              
45             sub _fetch_attribute_handler {
46 0     0   0 my($ref, $attr) = @_;
47 0         0 my $reftype = attributes::reftype($ref);
48 0   0     0 return (exists($fetch_attribute_handlers{$reftype}) and $fetch_attribute_handlers{$reftype}->{$attr});
49             }
50              
51             sub _decompose_attr {
52 8     8   7 my($raw_attr) = @_;
53 8         32 my($attr, $params_str) = $raw_attr =~ m/^(\w+)(?:\((.*)\))$/;
54              
55 8 100       35 my @params = defined($params_str) ? split(/\s*,\s*/, $params_str) : ();
56 8 100       19 $attr = $raw_attr unless defined $attr;
57 8         24 return ($attr, @params);
58             }
59              
60             sub modify_attributes {
61 8     8 0 861 my($package, $ref, @raw_attrs) = @_;
62              
63 8         6 my @not_recognized;
64 8         12 foreach my $raw_attr ( @raw_attrs ) {
65 8         16 my($attr, @params) = _decompose_attr($raw_attr);
66 8 50       17 if (my $handler = _modify_attribute_handler($ref, $attr)) {
67 8         18 $handler->($package, $ref, $attr, @params);
68             } else {
69 0         0 push @not_recognized, $raw_attr;
70             }
71             }
72              
73 7         14 return @not_recognized;
74             }
75              
76             my %stored_attributes_by_ref;
77              
78             sub fetch_attributes {
79 0     0 0 0 my($package, $ref) = @_;
80              
81 0         0 my $reftype = attributes::reftype($ref);
82 0         0 my @attrs;
83 0         0 foreach my $attr ( keys %{ $stored_attributes_by_ref{$ref} } ) {
  0         0  
84 0 0       0 if (my $handler = _fetch_attribute_handler($ref, $attr)) {
85 0         0 push @attrs, $handler->($package, $ref);
86             }
87             }
88 0         0 return @attrs;
89             }
90              
91             sub modify_code_overrides {
92 6     6 0 6 my($package, $coderef, $attr, @params) = @_;
93              
94 6   50     27 my $list = $stored_attributes_by_ref{$coderef}->{overrides} ||= [];
95 6         17 push @$list, @params;
96             }
97              
98             sub modify_scalar_role_property {
99 2     2 0 4 my($package, $scalar_ref, $attr, $name) = @_;
100              
101 2 100       6 unless ($name) {
102 1         8 Carp::croak('RoleParam attribute requires a name in parens. For example: my $var : RoleParam(var)');
103             }
104 1         10 $$scalar_ref = UR::Role::Param->new(name => $name, role_name => $package, varref => $scalar_ref);
105             }
106              
107             sub fetch_code_overrides {
108 0     0 0 0 my($package, $coderef) = @_;
109              
110             return sprintf('overrides(%s)',
111 0         0 join(', ', @{ $stored_attributes_by_ref{$coderef}->{overrides} }));
  0         0  
112             }
113              
114             sub get_overrides_for_coderef {
115 81657     81657 0 51750 my($ref) = @_;
116             return( exists($stored_attributes_by_ref{$ref}) && exists($stored_attributes_by_ref{$ref}->{overrides})
117 81657 100 66     178832 ? @{ $stored_attributes_by_ref{$ref}->{overrides} }
  19         60  
118             : ()
119             );
120             }
121              
122             1;