File Coverage

blib/lib/Moops/Keyword.pm
Criterion Covered Total %
statement 81 84 96.4
branch 15 18 83.3
condition 2 2 100.0
subroutine 25 26 96.1
pod 0 13 0.0
total 123 143 86.0


line stmt bran cond sub pod time code
1 34     34   14908 use v5.14;
  34         117  
2 34     34   204 use strict;
  34         295  
  34         1397  
3 34     34   223 use warnings FATAL => 'all';
  34         82  
  34         1653  
4 34     34   187 no warnings qw(void once uninitialized numeric);
  34         94  
  34         2889  
5              
6             package Moops::Keyword;
7              
8             our $AUTHORITY = 'cpan:TOBYINK';
9             our $VERSION = '0.038';
10              
11 34     34   256 use Moo;
  34         76  
  34         209  
12 34     34   32866 use B qw(perlstring);
  34         74  
  34         1848  
13 34     34   10389 use Devel::GlobalDestruction;
  34         13445  
  34         233  
14 34     34   2665 use Module::Runtime qw(module_notional_filename use_package_optimistically);
  34         67  
  34         270  
15 34     34   2102 use namespace::autoclean;
  34         152  
  34         394  
16              
17             has 'keyword' => (is => 'ro');
18             has 'ccstash' => (is => 'ro');
19             has 'package' => (is => 'ro');
20             has 'version' => (is => 'ro', predicate => 'has_version');
21             has 'relations' => (is => 'ro');
22             has 'is_empty' => (is => 'ro');
23             has 'imports' => (is => 'ro', predicate => 'has_imports');
24             has 'version_checks' => (is => 'ro');
25             has '_guarded' => (is => 'lazy', default => sub { [] });
26              
27 0     0 0 0 sub should_support_methods { 0 }
28              
29             sub BUILD
30             {
31 94     94 0 231733 my $self = shift;
32 94   100     1094 @{ $self->relations->{types} ||= [] }
33 94 100       183 or push @{$self->relations->{types}}, 'Types::Standard';
  90         788  
34             }
35              
36             sub generate_code
37             {
38 93     93 0 171 my $self = shift;
39 93         196 my $class = ref $self;
40 93         368 my $package = $self->package;
41            
42             # Create the package declaration and version
43 93         286 my $inject = "package $package;";
44 93 100       461 $inject .= (
45             $self->has_version
46 3         15 ? "BEGIN { our \$VERSION = '${\ $self->version }' };"
47             : "BEGIN { our \$VERSION = '' };"
48             );
49 93         180 $inject .= "BEGIN { \$INC{${\ perlstring module_notional_filename $package }} = __FILE__ };";
  93         321  
50            
51             # Standard imports
52 93         2802 $inject .= join q[], $self->generate_package_setup;
53            
54             # Additional imports
55 93 100       677 $inject .= $self->imports->generate_code($package) if $self->has_imports;
56            
57             # Stuff that must happen at runtime rather than compile time
58 93         353 $inject .= "'Moops'->at_runtime('$package');";
59            
60 93         178 my @guarded = @{ $self->_guarded };
  93         1896  
61 93         429 state $i = 0;
62 93 100       307 if (@guarded)
63             {
64 28         926 $inject .= sprintf(
65             'my $__GUARD__%d_%d = "Moops::Keyword"->scope_guard(sub { %s });',
66             ++$i,
67             100_000 + int(rand 899_000),
68             join(q[;], @guarded),
69             );
70             }
71            
72 93         465 return $inject;
73             }
74              
75             sub generate_package_setup
76             {
77 93     93 0 424 my $self = shift;
78            
79             return (
80 93 100       532 $self->generate_type_constraint_setup,
81             $self->generate_package_setup_oo,
82             ) if $self->is_empty;
83            
84             return (
85 73         380 'use Carp qw(confess);',
86             'use PerlX::Assert;',
87             'use PerlX::Define;',
88             'use Scalar::Util qw(blessed);',
89             'use Try::Tiny;',
90             'BEGIN { (*true, *false) = (\&Moops::_true, \&Moops::_false) };',
91             $self->generate_type_constraint_setup,
92             $self->generate_package_setup_oo,
93             $self->generate_package_setup_methods,
94             'use v5.14;',
95             'use strict;',
96             'no warnings;',
97             'use warnings FATAL => @Moops::FATAL_WARNINGS;',
98             );
99             }
100              
101             sub generate_package_setup_oo
102             {
103 10     10 0 55 return;
104             }
105              
106             sub generate_package_setup_methods
107             {
108 73     73 0 170 my $self = shift;
109 73         1670 my @args = $self->arguments_for_kavorka($self->package);
110 73         783 return "use Kavorka qw(@args);";
111             }
112              
113             sub generate_type_constraint_setup
114             {
115 93     93 0 204 my $self = shift;
116             return map {
117 93         331 my $lib = use_package_optimistically($_);
118             $lib->isa('Type::Library')
119             ? "use $lib -types;"
120             : $lib->can('type_names')
121             ? do {
122 1         491 require Type::Registry;
123 1         15800 "use $lib ('$lib'->type_names); BEGIN { 'Type::Registry'->for_me->add_types(q[$lib]) };"
124             }
125 93 50       3527411 : do {
    100          
126 0         0 require Carp;
127 0         0 Carp::croak("'$lib' is not a recognized type constraint library")
128             };
129 93 50       172 } @{ $self->relations->{types} || [] };
  93         449  
130             }
131              
132             sub arguments_for_kavorka
133             {
134 73     73 0 339 return qw/ multi fun /;
135             }
136              
137             sub known_relationships
138             {
139 186     186 0 1456 return qw/ types /;
140             }
141              
142             sub qualify_relationship
143             {
144 3     3 0 23 1;
145             }
146              
147             sub version_relationship
148             {
149 29     29 0 108 1;
150             }
151              
152             sub check_prerequisites
153             {
154 94     94 0 184 my $self = shift;
155 94         138 for my $prereq (@{$self->version_checks})
  94         468  
156             {
157 3 50       99 &use_package_optimistically(@$prereq) if defined $prereq->[1];
158             }
159             }
160              
161             sub _mk_guard
162             {
163 31     31   63 my $self = shift;
164 31         60 push @{$self->_guarded}, @_;
  31         619  
165             }
166              
167 34     34   39039 use Variable::Magic qw(wizard cast);
  34         85  
  34         7624  
168             sub scope_guard {
169 28     28 0 269 shift;
170             state $wiz = wizard(
171 28     28   106 data => sub { $_[1] },
172 28     28   60365 free => sub { $_[1]() },
173 28         199 );
174 28         847 cast my($magic), $wiz, $_[0];
175 28         77 \$magic;
176             }
177              
178             1;