File Coverage

blib/lib/Mite/Trait/HasConstructor.pm
Criterion Covered Total %
statement 48 49 97.9
branch 8 10 80.0
condition n/a
subroutine 11 11 100.0
pod n/a
total 67 70 95.7


line stmt bran cond sub pod time code
1 109     109   2530 use 5.010001;
  109         487  
2 109     109   668 use strict;
  109         265  
  109         2751  
3 109     109   588 use warnings;
  109         253  
  109         5672  
4              
5             use Mite::Miteception -role, -all;
6 109     109   720  
  109         312  
  109         953  
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '0.011000';
9              
10             requires qw(
11             linear_isa
12             _get_parent
13             _compile_meta
14             );
15              
16             around compilation_stages => sub {
17             my ( $next, $self ) = ( shift, shift );
18              
19             # Check if we are inheriting from a Mite class in this project
20             my $inherit_from_mite = do {
21             # First parent
22             my $first_isa = do {
23             my @isa = $self->linear_isa;
24             shift @isa;
25             shift @isa;
26             };
27             !! ( $first_isa and $self->_get_parent( $first_isa ) );
28             };
29              
30             my @stages = $self->$next( @_ );
31              
32             # Need a constructor if we're not inheriting from Mite,
33             # or if we define any new attributes.
34             push @stages, '_compile_new'
35             if !$inherit_from_mite
36             || keys %{ $self->attributes };
37              
38             # Only need these stages if not already inheriting from Mite
39             push @stages, qw(
40             _compile_buildall_method
41             ) unless $inherit_from_mite;
42              
43             return @stages;
44             };
45              
46             my $self = shift;
47             my @vars = ('$class', '$self', '$args', '$meta');
48 104     104   332  
49 104         498 return sprintf <<'CODE', $self->_compile_meta(@vars), $self->_compile_bless(@vars), $self->_compile_buildargs(@vars), $self->_compile_init_attributes(@vars), $self->_compile_buildall(@vars, '$no_build'), $self->_compile_strict_constructor(@vars);
50             # Standard Moose/Moo-style constructor
51 104         606 sub new {
52             my $class = ref($_[0]) ? ref(shift) : shift;
53             my $meta = %s;
54             my $self = %s;
55             my $args = %s;
56             my $no_build = delete $args->{__no_BUILD__};
57              
58             %s
59              
60             # Call BUILD methods
61             %s
62              
63             # Unrecognized parameters
64             %s
65              
66             return $self;
67             }
68             CODE
69             }
70              
71             my ( $self, $classvar, $selfvar, $argvar, $metavar ) = @_;
72              
73             my $simple_bless = "bless {}, $classvar";
74 104     104   450  
75             # Force parents to be loaded
76 104         368 $self->parents;
77              
78             # First parent with &new
79 104         667 my ( $first_isa ) = do {
80             my @isa = $self->linear_isa;
81             shift @isa;
82 104         272 no strict 'refs';
83 104         430 grep +(defined &{$_.'::new'}), @isa;
84 104         314 };
85 109     109   922  
  109         309  
  109         54495  
86 104         338 # If we're not inheriting from anything with a constructor: simple case
  22         162  
87             $first_isa or return $simple_bless;
88              
89             # Inheriting from a Mite class in this project: simple case
90 104 100       903 my $first_parent = $self->_get_parent( $first_isa )
91             and return $simple_bless;
92              
93 2 50       8 # Inheriting from a Moose/Moo/Mite/Class::Tiny class:
94             # call buildargs
95             # set $args->{__no_BUILD__}
96             # call parent class constructor
97             if ( $first_isa->can( 'BUILDALL' ) ) {
98             return sprintf 'do { my %s = %s; %s->{__no_BUILD__} = 1; %s->SUPER::new( %s ) }',
99             $argvar, $self->_compile_buildargs($classvar, $selfvar, $argvar, $metavar), $argvar, $classvar, $argvar;
100 2 100       50 }
101 1         7  
102             # Inheriting from some random class
103             # call FOREIGNBUILDARGS if it exists
104             # pass return value or @_ to parent class constructor
105             return sprintf '%s->SUPER::new( %s->{HAS_FOREIGNBUILDARGS} ? %s->FOREIGNBUILDARGS( @_ ) : @_ )',
106             $classvar, $metavar, $classvar;
107             }
108 1         12  
109             my ( $self, $classvar, $selfvar, $argvar, $metavar ) = @_;
110             return sprintf '%s->{HAS_BUILDARGS} ? %s->BUILDARGS( @_ ) : { ( @_ == 1 ) ? %%{$_[0]} : @_ }',
111             $metavar, $classvar;
112             }
113 105     105   412  
114 105         928 my ( $self, $classvar, $selfvar, $argvar, $metavar ) = @_;
115              
116             my @allowed =
117             grep { defined $_ }
118             map { ( $_->init_arg, $_->_all_aliases ) }
119 104     104   417 values %{ $self->all_attributes };
120             my $check = do {
121             local $Type::Tiny::AvoidCallbacks = 1;
122 132         504 my $enum = Enum->of( @allowed );
123 129         463 $enum->can( '_regexp' ) # not part of official API
124 104         266 ? sprintf( '/\\A%s\\z/', $enum->_regexp )
  104         2654  
125 104         284 : $enum->inline_check( '$_' );
126 104         369 };
127 104         753  
128 104 100       128035 my $code = sprintf 'my @unknown = grep not( %s ), keys %%{%s}; @unknown and %s( "Unexpected keys in constructor: " . join( q[, ], sort @unknown ) );',
129             $check, $argvar, $self->_function_for_croak;
130             if ( my $autolax = $self->autolax ) {
131             $code = "if ( $autolax ) { $code }";
132             }
133 104         28632 return $code;
134             }
135 104 50       874  
136 0         0 my ( $self, $classvar, $selfvar, $argvar, $metavar, $nobuildvar ) = @_;
137             return sprintf '%s->BUILDALL( %s ) if ( ! %s and @{ %s->{BUILD} || [] } );',
138 104         4880 $selfvar, $argvar, $nobuildvar, $metavar;
139             }
140              
141             my $self = shift;
142 104     104   492  
143 104         892 return sprintf <<'CODE', $self->_compile_meta( '$class', '$_[0]', '$_[1]', '$meta' ),
144             # Used by constructor to call BUILD methods
145             sub BUILDALL {
146             my $class = ref( $_[0] );
147             my $meta = %s;
148 90     90   252 $_->( @_ ) for @{ $meta->{BUILD} || [] };
149             }
150 90         482 CODE
151             }
152              
153             1;