File Coverage

blib/lib/Class/XSConstructor.pm
Criterion Covered Total %
statement 82 89 92.1
branch 23 32 71.8
condition 5 12 41.6
subroutine 14 15 93.3
pod 0 3 0.0
total 124 151 82.1


line stmt bran cond sub pod time code
1 4     4   265148 use 5.008008;
  4         30  
2 4     4   20 use strict;
  4         6  
  4         78  
3 4     4   15 use warnings;
  4         6  
  4         83  
4 4     4   15 use XSLoader ();
  4         9  
  4         201  
5              
6             package Class::XSConstructor;
7              
8             our $AUTHORITY = 'cpan:TOBYINK';
9             our $VERSION = '0.008';
10              
11 4     4   1074 use Exporter::Tiny 1.000000 qw( mkopt );
  4         7290  
  4         16  
12 4     4   2085 use Ref::Util 0.100 qw( is_plain_arrayref is_plain_hashref is_blessed_ref is_coderef );
  4         4090  
  4         272  
13 4     4   23 use List::Util 1.45 qw( uniq );
  4         49  
  4         422  
14              
15             sub import {
16 8     8   2389 my $class = shift;
17 8   33     39 my $caller = our($SETUP_FOR) || caller;
18            
19 8 50       16 if (our $REDEFINE) {
20 4     4   23 no warnings 'redefine';
  4         8  
  4         1843  
21 0         0 install_constructor("$caller\::new");
22             }
23             else {
24 8         39 install_constructor("$caller\::new");
25             }
26 8         23 inheritance_stuff($caller);
27            
28 8         14 my ($HAS, $REQUIRED, $ISA, $BUILDALL) = get_vars($caller);
29 8         9 $$BUILDALL = undef;
30            
31 8         12 for my $pair (@{ mkopt \@_ }) {
  8         18  
32 20         188 my ($name, $thing) = @$pair;
33 20         22 my %spec;
34            
35 20 50 66     95 if (is_plain_arrayref($thing)) {
    50 33        
    100          
    50          
    100          
    50          
36 0         0 %spec = @$thing;
37             }
38             elsif (is_plain_hashref($thing)) {
39 0         0 %spec = %$thing;
40             }
41             elsif (is_blessed_ref($thing) and $thing->can('compiled_check')) {
42 1         13 %spec = (isa => $thing->compiled_check);
43             }
44             elsif (is_blessed_ref($thing) and $thing->can('check')) {
45             # Support it for compatibility with more basic Type::API::Constraint
46             # implementations, but this will be slowwwwww!
47 0     0   0 %spec = (isa => sub { !! $thing->check($_[0]) });
  0         0  
48             }
49             elsif (is_coderef($thing)) {
50 1         2 %spec = (isa => $thing);
51             }
52             elsif (defined $thing) {
53 0         0 Exporter::Tiny::_croak("What is %s???", $thing);
54             }
55            
56 20 100       62 if ($name =~ /\A(.*)\!\z/) {
57 8         22 $name = $1;
58 8         15 $spec{required} = !!1;
59             }
60            
61 20         60 my @unknown_keys = sort grep !/\A(isa|required|is)\z/, keys %spec;
62 20 50       53 if (@unknown_keys) {
63 0         0 Exporter::Tiny::_croak("Unknown keys in spec: %d", join ", ", @unknown_keys);
64             }
65            
66 20         39 push @$HAS, $name;
67 20 100       43 push @$REQUIRED, $name if $spec{required};
68 20 100       6335 $ISA->{$name} = $spec{isa} if $spec{isa};
69             }
70             }
71              
72             sub get_vars {
73 20     20 0 26 my $caller = shift;
74 4     4   26 no strict 'refs';
  4         6  
  4         1005  
75             (
76 20         57 \@{"$caller\::__XSCON_HAS"},
77 20         59 \@{"$caller\::__XSCON_REQUIRED"},
78 20         39 \%{"$caller\::__XSCON_ISA"},
79 20         25 \${"$caller\::__XSCON_BUILD"},
  20         58  
80             );
81             }
82              
83             sub inheritance_stuff {
84 8     8 0 10 my $caller = shift;
85            
86 8 50       44 require( $] >= 5.010 ? "mro.pm" : "MRO/Compat.pm" );
87            
88 8         13 my @isa = reverse @{ mro::get_linear_isa($caller) };
  8         43  
89 8         44 pop @isa; # discard $caller itself
90 8 100       24 return unless @isa;
91            
92 4         13 my ($HAS, $REQUIRED, $ISA) = get_vars($caller);
93 4         9 foreach my $parent (@isa) {
94 4         9 my ($pHAS, $pREQUIRED, $pISA) = get_vars($parent);
95 4         25 @$HAS = uniq(@$HAS, @$pHAS);
96 4         12 @$REQUIRED = uniq(@$REQUIRED, @$pREQUIRED);
97 4         15 $ISA->{$_} = $pISA->{$_} for keys %$pISA;
98             }
99             }
100              
101             sub populate_build {
102 4   33 4 0 7747 my $caller = ref($_[0]) || $_[0];
103 4         13 my (undef, undef, undef, $BUILDALL) = get_vars($caller);
104            
105 4 100       44 if (!$caller->can('BUILD')) {
106 3         6 $$BUILDALL = 0;
107 3         9 return;
108             }
109            
110 1 50       8 require( $] >= 5.010 ? "mro.pm" : "MRO/Compat.pm" );
111 4     4   27 no strict 'refs';
  4         7  
  4         384  
112            
113             $$BUILDALL = [
114 2 50       2 map { ( *{$_}{CODE} ) ? ( *{$_}{CODE} ) : () }
  2         7  
  2         5  
115 1         3 map { "$_\::BUILD" } reverse @{ mro::get_linear_isa($caller) }
  2         5  
  1         5  
116             ];
117            
118 1         4 return;
119             }
120              
121             __PACKAGE__->XSLoader::load($VERSION);
122              
123             1;
124              
125             __END__