File Coverage

blib/lib/MooX/XSConstructor.pm
Criterion Covered Total %
statement 54 59 91.5
branch 13 24 54.1
condition 5 12 41.6
subroutine 10 10 100.0
pod 0 2 0.0
total 82 107 76.6


line stmt bran cond sub pod time code
1 1     1   88049 use 5.008001;
  1         4  
2 1     1   5 use strict;
  1         2  
  1         19  
3 1     1   10 use warnings;
  1         2  
  1         67  
4              
5             package MooX::XSConstructor;
6              
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '0.002';
9              
10 1     1   6 use Moo 1.006000 ();
  1         33  
  1         25  
11 1     1   6 use Scalar::Util qw(blessed);
  1         2  
  1         48  
12 1     1   481 use Hook::AfterRuntime;
  1         2705  
  1         624  
13              
14             my $safe_spec = qr/\A(index|required|is|isa|builder|default|lazy|predicate|clearer|reader|writer)\z/;
15              
16             sub is_suitable_class {
17 1     1 0 2 my $self = shift;
18 1         3 my ($klass, $maybe_spec) = @_;
19            
20 1         5 my $ba = $klass->can('BUILDARGS');
21 1 50       5 return if !$ba;
22 1 50       4 return if $ba != \&Moo::Object::BUILDARGS;
23 1 50       13 return if $klass->can('FOREIGNBUILDARGS');
24            
25 1 50       5 my %spec = %{ $maybe_spec or Moo->_constructor_maker_for($klass)->all_attribute_specs };
  1         10  
26 1         5 my @attributes = sort { $spec{$a}{index} <=> $spec{$b}{index} } keys %spec;
  1         7  
27            
28 1         9 for my $attr (@attributes) {
29 2 50 33     10 if ($spec{$attr}{isa} and !blessed($spec{$attr}{isa})) {
30 0         0 return;
31             }
32 2 50 33     7 if ($spec{$attr}{isa} and !$spec{$attr}{isa}->can('compiled_check')) {
33 0         0 return;
34             }
35 2 50 33     7 if ($spec{$attr}{default} and not $spec{$attr}{lazy}) {
36 0         0 return;
37             }
38 2 50 66     8 if ($spec{$attr}{builder} and not $spec{$attr}{lazy}) {
39 0         0 return;
40             }
41 2 50       8 if (my @unsafe = grep { $_ !~ $safe_spec } keys %{ $spec{$attr} }) {
  9         48  
  2         8  
42             # print Dumper \@unsafe;
43 0         0 return;
44             }
45             }
46            
47 1         4 return "yay!";
48             }
49              
50             sub setup_for {
51 1     1 0 3 my $self = shift;
52 1         4 my ($klass) = @_;
53            
54 1         2 my %spec = %{ Moo->_constructor_maker_for($klass)->all_attribute_specs };
  1         3  
55 1 50       16 return unless $self->is_suitable_class($klass, \%spec);
56            
57             my @optlist =
58             map {
59 2         5 my $attrbang = my $attr = $_;
60 2 100       6 $attrbang .= '!' if $spec{$attr}{required};
61 2 50       7 $spec{$attr}{isa} ? ($attrbang, $spec{$attr}{isa}) : ($attrbang);
62             }
63 1         5 sort { $spec{$a}{index} <=> $spec{$b}{index} }
  1         4  
64             keys %spec;
65            
66 1         512 require Class::XSConstructor;
67 1         7788 local $Class::XSConstructor::SETUP_FOR = $klass;
68 1         3 local $Class::XSConstructor::REDEFINE = !!1;
69 1         4 Class::XSConstructor->import(@optlist);
70             }
71              
72             sub import {
73 1     1   13 my $self = shift;
74 1         2 my $caller = caller;
75             after_runtime {
76 1     1   22380 $self->setup_for($caller);
77 1         7 };
78             }
79              
80             1;
81              
82             __END__