File Coverage

blib/lib/Class/Accessor/Array.pm
Criterion Covered Total %
statement 71 73 97.2
branch 17 30 56.6
condition 2 2 100.0
subroutine 3 3 100.0
pod n/a
total 93 108 86.1


line stmt bran cond sub pod time code
1             package Class::Accessor::Array;
2              
3             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
4             our $DATE = '2021-08-03'; # DATE
5             our $DIST = 'Class-Accessor-Array'; # DIST
6             our $VERSION = '0.032'; # VERSION
7              
8             #IFUNBUILT
9             # use strict 'subs', 'vars';
10             # use warnings;
11             #END IFUNBUILT
12              
13             sub import {
14 3     3   930 my ($class0, $spec) = @_;
15 3         15 my $caller = caller();
16              
17 3         59 my $class = $caller;
18              
19             #IFUNBUILT
20             # no warnings 'redefine';
21             #END IFUNBUILT
22              
23             # user does not specify 'accessors', perhaps she just loads it. so we just
24             # return.
25 3 50       11 return unless exists $spec->{accessors};
26              
27             # generate accessors
28 3         5 for my $meth (keys %{$spec->{accessors}}) {
  3         13  
29 5         12 my $idx = $spec->{accessors}{$meth};
30 5         10 my $code_str = 'sub (;$) { ';
31 5         12 $code_str .= "\$_[0][$idx] = \$_[1] if \@_ > 1; ";
32 5         9 $code_str .= "\$_[0][$idx]; ";
33 5         7 $code_str .= "}";
34             #say "D:accessor code for $meth: ", $code_str;
35 5 50   2   518 *{"$class\::$meth"} = eval $code_str;
  5 50       31  
  2 50       31  
  2 50       23  
  4 50       74  
  4         45  
  1         27  
  1         3  
  1         32  
  1         3  
  4         65  
  4         47  
36 5 50       21 die if $@;
37             }
38              
39             # generate constructor
40             {
41 3         6 my $code_str;
  3         6  
42 3         6 $code_str = 'sub { my ($class, %args) = @_;';
43 3 100       5 if (@{"$class\::ISA"}) {
  3         17  
44 1         3 $code_str .= ' require '.${"$class\::ISA"}[0].';';
  1         4  
45 1         6 $code_str .= ' my $self = '.${"$class\::ISA"}[0].'->new(map {($_=>delete $args{$_})}'.
46 1         2 ' grep {'.(join " && ", map {'$_ ne \''.$_.'\''} keys %{$spec->{accessors}}).'} keys %args);';
  1         6  
  1         4  
47 1         3 $code_str .= ' $self = bless $self, \''.$class.'\';';
48             } else {
49 2         5 $code_str .= ' my $self = bless [], $class;';
50             }
51 3         5 $code_str .= ' for my $key (grep {'.(join " || ", map {'$_ eq \''.$_.'\''} keys %{$spec->{accessors}}).'} keys %args) { $self->$key(delete $args{$key}) }';
  5         19  
  3         11  
52 3         7 $code_str .= ' die "Unknown $class attributes in constructor: ".join(", ", sort keys %args) if keys %args;';
53 3         5 $code_str .= ' $self }';
54              
55             #print "D:constructor code for class $class: ", $code_str, "\n";
56 3   100     14 my $constructor = $spec->{constructor} || "new";
57 3 50       5 unless (*{"$class\::$constructor"}{CODE}) {
  3         16  
58 3 50   3   603 *{"$class\::$constructor"} = eval $code_str;
  3 0       14  
  3 50       5101  
  3 100       23  
  3 100       33  
  3         106  
  4         11  
  2         6  
  2         6  
  1         5  
  1         22  
  2         7  
  2         6  
  1         1037  
  1         4  
  1         4  
  0         0  
  0         0  
  1         5  
  1         3  
  6         2515  
  6         19  
  6         21  
  6         41  
  4         91  
  6         65  
  4         48  
59 3 50       103 die if $@;
60             };
61             }
62             }
63              
64             1;
65             # ABSTRACT: Generate accessors/constructor for array-based object
66              
67             __END__