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 3 3 100.0
total 127 151 84.1


line stmt bran cond sub pod time code
1 4     4   356013 use 5.008008;
  4         37  
2 4     4   21 use strict;
  4         8  
  4         94  
3 4     4   21 use warnings;
  4         8  
  4         144  
4 4     4   25 use XSLoader ();
  4         14  
  4         276  
5              
6             package Class::XSConstructor;
7              
8             our $AUTHORITY = 'cpan:TOBYINK';
9             our $VERSION = '0.009';
10              
11 4     4   1432 use Exporter::Tiny 1.000000 qw( mkopt );
  4         10033  
  4         22  
12 4     4   2902 use Ref::Util 0.100 qw( is_plain_arrayref is_plain_hashref is_blessed_ref is_coderef );
  4         6033  
  4         356  
13 4     4   32 use List::Util 1.45 qw( uniq );
  4         67  
  4         611  
14              
15             sub import {
16 8     8   3198 my $class = shift;
17 8   33     52 my $caller = our($SETUP_FOR) || caller;
18            
19 8 50       22 if (our $REDEFINE) {
20 4     4   30 no warnings 'redefine';
  4         9  
  4         2029  
21 0         0 install_constructor("$caller\::new");
22             }
23             else {
24 8         53 install_constructor("$caller\::new");
25             }
26 8         29 inheritance_stuff($caller);
27            
28 8         18 my ($HAS, $REQUIRED, $ISA, $BUILDALL) = get_vars($caller);
29 8         19 $$BUILDALL = undef;
30            
31 8         11 for my $pair (@{ mkopt \@_ }) {
  8         28  
32 20         249 my ($name, $thing) = @$pair;
33 20         29 my %spec;
34            
35 20 50 66     117 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         19 %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         3 %spec = (isa => $thing);
51             }
52             elsif (defined $thing) {
53 0         0 Exporter::Tiny::_croak("What is %s???", $thing);
54             }
55            
56 20 100       78 if ($name =~ /\A(.*)\!\z/) {
57 8         27 $name = $1;
58 8         19 $spec{required} = !!1;
59             }
60            
61 20         79 my @unknown_keys = sort grep !/\A(isa|required|is)\z/, keys %spec;
62 20 50       50 if (@unknown_keys) {
63 0         0 Exporter::Tiny::_croak("Unknown keys in spec: %d", join ", ", @unknown_keys);
64             }
65            
66 20         51 push @$HAS, $name;
67 20 100       62 push @$REQUIRED, $name if $spec{required};
68 20 100       8010 $ISA->{$name} = $spec{isa} if $spec{isa};
69             }
70             }
71              
72             sub get_vars {
73 20     20 1 35 my $caller = shift;
74 4     4   44 no strict 'refs';
  4         7  
  4         1431  
75             (
76 20         73 \@{"$caller\::__XSCON_HAS"},
77 20         59 \@{"$caller\::__XSCON_REQUIRED"},
78 20         52 \%{"$caller\::__XSCON_ISA"},
79 20         38 \${"$caller\::__XSCON_BUILD"},
  20         86  
80             );
81             }
82              
83             sub inheritance_stuff {
84 8     8 1 16 my $caller = shift;
85            
86 8 50       53 require( $] >= 5.010 ? "mro.pm" : "MRO/Compat.pm" );
87            
88 8         14 my @isa = reverse @{ mro::get_linear_isa($caller) };
  8         53  
89 8         19 pop @isa; # discard $caller itself
90 8 100       29 return unless @isa;
91            
92 4         16 my ($HAS, $REQUIRED, $ISA) = get_vars($caller);
93 4         12 foreach my $parent (@isa) {
94 4         9 my ($pHAS, $pREQUIRED, $pISA) = get_vars($parent);
95 4         35 @$HAS = uniq(@$HAS, @$pHAS);
96 4         19 @$REQUIRED = uniq(@$REQUIRED, @$pREQUIRED);
97 4         22 $ISA->{$_} = $pISA->{$_} for keys %$pISA;
98             }
99             }
100              
101             sub populate_build {
102 4   33 4 1 10841 my $caller = ref($_[0]) || $_[0];
103 4         19 my (undef, undef, undef, $BUILDALL) = get_vars($caller);
104            
105 4 100       57 if (!$caller->can('BUILD')) {
106 3         9 $$BUILDALL = 0;
107 3         12 return;
108             }
109            
110 1 50       12 require( $] >= 5.010 ? "mro.pm" : "MRO/Compat.pm" );
111 4     4   53 no strict 'refs';
  4         8  
  4         522  
112            
113             $$BUILDALL = [
114 2 50       5 map { ( *{$_}{CODE} ) ? ( *{$_}{CODE} ) : () }
  2         8  
  2         7  
115 1         3 map { "$_\::BUILD" } reverse @{ mro::get_linear_isa($caller) }
  2         6  
  1         7  
116             ];
117            
118 1         7 return;
119             }
120              
121             __PACKAGE__->XSLoader::load($VERSION);
122              
123             1;
124              
125             __END__