File Coverage

blib/lib/Type/Library/Compiler.pm
Criterion Covered Total %
statement 14 62 22.5
branch 0 14 0.0
condition 0 3 0.0
subroutine 5 14 35.7
pod 3 3 100.0
total 22 96 22.9


line stmt bran cond sub pod time code
1 1     1   438 use 5.008001;
  1         4  
2 1     1   4 use strict;
  1         2  
  1         16  
3 1     1   4 use warnings;
  1         2  
  1         66  
4              
5             package Type::Library::Compiler;
6              
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '0.006';
9              
10 1     1   365 use Type::Library::Compiler::Mite -all;
  1         2  
  1         4  
11 1     1   6 use B ();
  1         2  
  1         983  
12              
13             has types => (
14             is => ro,
15             isa => 'Map[NonEmptyStr,Object]',
16 0     0     builder => sub { [] },
17             );
18              
19             has pod => (
20             is => rw,
21             isa => 'Bool',
22             coerce => true,
23             default => true,
24             );
25              
26             has destination_module => (
27             is => ro,
28             isa => 'NonEmptyStr',
29             required => true,
30             );
31              
32             has constraint_module => (
33             is => ro,
34             isa => 'NonEmptyStr',
35             builder => sub {
36 0     0     sprintf '%s::TypeConstraint', shift->destination_module;
37             },
38             );
39              
40             has destination_filename => (
41             is => lazy,
42             isa => 'NonEmptyStr',
43             builder => sub {
44 0     0     ( my $module = shift->destination_module ) =~ s{::}{/}g;
45 0           return sprintf 'lib/%s.pm', $module;
46             },
47             );
48              
49             sub compile_to_file {
50 0     0 1   my $self = shift;
51              
52 0 0         open( my $fh, '>', $self->destination_filename )
53             or croak( 'Could not open %s: %s', $self->destination_filename, $! );
54              
55 0           print { $fh } $self->compile_to_string;
  0            
56              
57 0 0         close( $fh )
58             or croak( 'Could not close %s: %s', $self->destination_filename, $! );
59              
60 0           return;
61             }
62              
63             sub compile_to_string {
64 0     0 1   my $self = shift;
65              
66 0 0         my @type_names = sort keys %{ $self->types or {} };
  0            
67              
68 0           my $code = '';
69 0           $code .= $self->_compile_header;
70 0           $code .= $self->_compile_type( $self->types->{$_}, $_ ) for @type_names;
71 0           $code .= $self->_compile_footer;
72              
73 0 0         if ( $self->pod ) {
74 0           $code .= $self->_compile_pod_header;
75 0           $code .= $self->_compile_pod_type( $self->types->{$_}, $_ ) for @type_names;
76 0           $code .= $self->_compile_pod_footer;
77             }
78              
79 0           return $code;
80             }
81              
82             sub _compile_header {
83 0     0     my $self = shift;
84              
85 0           return sprintf <<'CODE', $self->destination_module, $self->VERSION, $self->constraint_module, $self->destination_module;
86             use 5.008001;
87             use strict;
88             use warnings;
89              
90             package %s;
91              
92             use Exporter ();
93             use Carp qw( croak );
94              
95             our $TLC_VERSION = "%s";
96             our @ISA = qw( Exporter );
97             our @EXPORT;
98             our @EXPORT_OK;
99             our %%EXPORT_TAGS = (
100             is => [],
101             types => [],
102             assert => [],
103             );
104              
105             BEGIN {
106             package %s;
107             our $LIBRARY = "%s";
108              
109             use overload (
110             fallback => !!1,
111             '|' => 'union',
112             bool => sub { !! 1 },
113             '""' => sub { shift->[1] },
114             '&{}' => sub {
115             my $self = shift;
116             return sub { $self->assert_return( @_ ) };
117             },
118             );
119              
120             sub union {
121             my @types = grep ref( $_ ), @_;
122             my @codes = map $_->[0], @types;
123             bless [
124             sub { for ( @codes ) { return 1 if $_->(@_) } return 0 },
125             join( '|', map $_->[1], @types ),
126             \@types,
127             ], __PACKAGE__;
128             }
129              
130             sub check {
131             $_[0][0]->( $_[1] );
132             }
133              
134             sub get_message {
135             sprintf '%%s did not pass type constraint "%%s"',
136             defined( $_[1] ) ? $_[1] : 'Undef',
137             $_[0][1];
138             }
139              
140             sub validate {
141             $_[0][0]->( $_[1] )
142             ? undef
143             : $_[0]->get_message( $_[1] );
144             }
145              
146             sub assert_valid {
147             $_[0][0]->( $_[1] )
148             ? 1
149             : Carp::croak( $_[0]->get_message( $_[1] ) );
150             }
151              
152             sub assert_return {
153             $_[0][0]->( $_[1] )
154             ? $_[1]
155             : Carp::croak( $_[0]->get_message( $_[1] ) );
156             }
157              
158             sub to_TypeTiny {
159             my ( $coderef, $name, $library, $origname ) = @{ +shift };
160             if ( ref $library eq 'ARRAY' ) {
161             require Type::Tiny::Union;
162             return 'Type::Tiny::Union'->new(
163             display_name => $name,
164             type_constraints => [ map $_->to_TypeTiny, @$library ],
165             );
166             }
167             if ( $library ) {
168             local $@;
169             eval "require $library; 1" or die $@;
170             my $type = $library->get_type( $origname );
171             return $type if $type;
172             }
173             require Type::Tiny;
174             return 'Type::Tiny'->new(
175             name => $name,
176             constraint => sub { $coderef->( $_ ) },
177             inlined => sub { sprintf '%%s::is_%%s(%%s)', $LIBRARY, $name, pop }
178             );
179             }
180              
181             sub DOES {
182             return 1 if $_[1] eq 'Type::API::Constraint';
183             return 1 if $_[1] eq 'Type::Library::Compiler::TypeConstraint';
184             shift->DOES( @_ );
185             }
186             };
187              
188             CODE
189             }
190              
191             sub _compile_footer {
192 0     0     my $self = shift;
193              
194 0           return <<'CODE';
195              
196             1;
197             __END__