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   425 use 5.008001;
  1         4  
2 1     1   4 use strict;
  1         2  
  1         16  
3 1     1   4 use warnings;
  1         2  
  1         61  
4              
5             package Type::Library::Compiler;
6              
7             our $AUTHORITY = 'cpan:TOBYINK';
8             our $VERSION = '0.004';
9              
10 1     1   373 use Type::Library::Compiler::Mite -all;
  1         3  
  1         4  
11 1     1   6 use B ();
  1         2  
  1         1069  
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->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 @ISA = qw( Exporter );
96             our @EXPORT;
97             our @EXPORT_OK;
98             our %%EXPORT_TAGS = (
99             is => [],
100             types => [],
101             assert => [],
102             );
103              
104             BEGIN {
105             package %s;
106             our $LIBRARY = "%s";
107              
108             use overload (
109             fallback => !!1,
110             bool => sub { !! 1 },
111             '""' => sub { shift->[1] },
112             '&{}' => sub {
113             my $self = shift;
114             return sub { $self->assert_return( @_ ) };
115             },
116             );
117              
118             sub check {
119             $_[0][0]->( $_[1] );
120             }
121              
122             sub get_message {
123             sprintf '%%s did not pass type constraint "%%s"',
124             defined( $_[1] ) ? $_[1] : 'Undef',
125             $_[0][1];
126             }
127              
128             sub validate {
129             $_[0][0]->( $_[1] )
130             ? undef
131             : $_[0]->get_message( $_[1] );
132             }
133              
134             sub assert_valid {
135             $_[0][0]->( $_[1] )
136             ? 1
137             : Carp::croak( $_[0]->get_message( $_[1] ) );
138             }
139              
140             sub assert_return {
141             $_[0][0]->( $_[1] )
142             ? $_[1]
143             : Carp::croak( $_[0]->get_message( $_[1] ) );
144             }
145              
146             sub to_TypeTiny {
147             my ( $coderef, $name, $library, $origname ) = @{ +shift };
148             if ( $library ) {
149             local $@;
150             eval "require $library; 1" or die $@;
151             my $type = $library->get_type( $origname );
152             return $type if $type;
153             }
154             require Type::Tiny;
155             return 'Type::Tiny'->new(
156             name => $name,
157             constraint => sub { $coderef->( $_ ) },
158             inlined => sub { sprintf '%%s::is_%%s(%%s)', $LIBRARY, $name, pop }
159             );
160             }
161              
162             sub DOES {
163             return 1 if $_[1] eq 'Type::API::Constraint';
164             return 1 if $_[1] eq 'Type::Library::Compiler::TypeConstraint';
165             shift->DOES( @_ );
166             }
167             };
168              
169             CODE
170             }
171              
172             sub _compile_footer {
173 0     0     my $self = shift;
174              
175 0           return <<'CODE';
176              
177             1;
178             __END__