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   15608 use v5.14;
  34         119  
2 34     34   211 use strict;
  34         281  
  34         1385  
3 34     34   251 use warnings FATAL => 'all';
  34         63  
  34         1576  
4 34     34   203 no warnings qw(void once uninitialized numeric);
  34         57  
  34         2888  
5              
6             package Moops::Keyword;
7              
8             our $AUTHORITY = 'cpan:TOBYINK';
9             our $VERSION = '0.037';
10              
11 34     34   226 use Moo;
  34         102  
  34         195  
12 34     34   33610 use B qw(perlstring);
  34         86  
  34         1807  
13 34     34   11084 use Devel::GlobalDestruction;
  34         13667  
  34         237  
14 34     34   2617 use Module::Runtime qw(module_notional_filename use_package_optimistically);
  34         69  
  34         240  
15 34     34   2036 use namespace::autoclean;
  34         118  
  34         370  
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 231457 my $self = shift;
32 94   100     1098 @{ $self->relations->{types} ||= [] }
33 94 100       244 or push @{$self->relations->{types}}, 'Types::Standard';
  90         822  
34             }
35              
36             sub generate_code
37             {
38 93     93 0 168 my $self = shift;
39 93         183 my $class = ref $self;
40 93         395 my $package = $self->package;
41            
42             # Create the package declaration and version
43 93         291 my $inject = "package $package;";
44 93 100       441 $inject .= (
45             $self->has_version
46 3         14 ? "BEGIN { our \$VERSION = '${\ $self->version }' };"
47             : "BEGIN { our \$VERSION = '' };"
48             );
49 93         185 $inject .= "BEGIN { \$INC{${\ perlstring module_notional_filename $package }} = __FILE__ };";
  93         351  
50            
51             # Standard imports
52 93         2802 $inject .= join q[], $self->generate_package_setup;
53            
54             # Additional imports
55 93 100       676 $inject .= $self->imports->generate_code($package) if $self->has_imports;
56            
57             # Stuff that must happen at runtime rather than compile time
58 93         403 $inject .= "'Moops'->at_runtime('$package');";
59            
60 93         194 my @guarded = @{ $self->_guarded };
  93         1935  
61 93         412 state $i = 0;
62 93 100       332 if (@guarded)
63             {
64 28         929 $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         535 return $inject;
73             }
74              
75             sub generate_package_setup
76             {
77 93     93 0 433 my $self = shift;
78            
79             return (
80 93 100       554 $self->generate_type_constraint_setup,
81             $self->generate_package_setup_oo,
82             ) if $self->is_empty;
83            
84             return (
85 73         359 '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 50 return;
104             }
105              
106             sub generate_package_setup_methods
107             {
108 73     73 0 174 my $self = shift;
109 73         1650 my @args = $self->arguments_for_kavorka($self->package);
110 73         780 return "use Kavorka qw(@args);";
111             }
112              
113             sub generate_type_constraint_setup
114             {
115 93     93 0 181 my $self = shift;
116             return map {
117 93         330 my $lib = use_package_optimistically($_);
118             $lib->isa('Type::Library')
119             ? "use $lib -types;"
120             : $lib->can('type_names')
121             ? do {
122 1         546 require Type::Registry;
123 1         12948 "use $lib ('$lib'->type_names); BEGIN { 'Type::Registry'->for_me->add_types(q[$lib]) };"
124             }
125 93 50       3354007 : do {
    100          
126 0         0 require Carp;
127 0         0 Carp::croak("'$lib' is not a recognized type constraint library")
128             };
129 93 50       165 } @{ $self->relations->{types} || [] };
  93         465  
130             }
131              
132             sub arguments_for_kavorka
133             {
134 73     73 0 355 return qw/ multi fun /;
135             }
136              
137             sub known_relationships
138             {
139 186     186 0 1522 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 103 1;
150             }
151              
152             sub check_prerequisites
153             {
154 94     94 0 188 my $self = shift;
155 94         146 for my $prereq (@{$self->version_checks})
  94         463  
156             {
157 3 50       105 &use_package_optimistically(@$prereq) if defined $prereq->[1];
158             }
159             }
160              
161             sub _mk_guard
162             {
163 31     31   75 my $self = shift;
164 31         56 push @{$self->_guarded}, @_;
  31         647  
165             }
166              
167 34     34   39571 use Variable::Magic qw(wizard cast);
  34         84  
  34         7263  
168             sub scope_guard {
169 28     28 0 291 shift;
170             state $wiz = wizard(
171 28     28   86 data => sub { $_[1] },
172 28     28   58591 free => sub { $_[1]() },
173 28         240 );
174 28         828 cast my($magic), $wiz, $_[0];
175 28         144 \$magic;
176             }
177              
178             1;