File Coverage

blib/lib/Dancer2/Core/Role/DSL.pm
Criterion Covered Total %
statement 52 56 92.8
branch 11 16 68.7
condition n/a
subroutine 14 14 100.0
pod 0 3 0.0
total 77 89 86.5


line stmt bran cond sub pod time code
1             package Dancer2::Core::Role::DSL;
2             # ABSTRACT: Role for DSL
3             $Dancer2::Core::Role::DSL::VERSION = '2.0.1';
4 143     1032   357730 use Moo::Role;
  143         21700  
  143         1330  
5 143     143   89179 use Dancer2::Core::Types;
  143         442  
  143         1668  
6 143     143   2228378 use Carp 'croak';
  143         420  
  143         13007  
7 143     143   1212 use Scalar::Util qw();
  143         384  
  143         62654  
8              
9             with 'Dancer2::Core::Role::Hookable';
10              
11             has app => ( is => 'ro', required => 1 );
12              
13             has keywords => (
14             is => 'rw',
15             isa => HashRef,
16             lazy => 1,
17             builder => '_build_dsl_keywords',
18             );
19              
20             sub _build_dsl_keywords {
21 220     220   3020 my ($self) = @_;
22 220 50       2406 $self->can('dsl_keywords')
23             ? $self->dsl_keywords
24             : {};
25             }
26              
27             sub register {
28 2     2 0 28 my ( $self, $keyword, $is_global ) = @_;
29 2         29 my $keywords = $self->keywords;
30 2         49 my $pkg = ref($self);
31 2         6 $pkg =~ s/__WITH__.+$//;
32              
33 2 50       12 if ( exists $keywords->{$keyword} ) {
34 0         0 my $reg_pkg = $keywords->{$keyword}{'pkg'};
35 0         0 $reg_pkg =~ s/__WITH__.+$//;
36 0 0       0 $reg_pkg eq $pkg and return;
37              
38 0         0 croak "[$pkg] Keyword $keyword already registered by $reg_pkg";
39             }
40              
41 2         14 $keywords->{$keyword} = { is_global => $is_global, pkg => $pkg };
42             }
43              
44 29     29 0 87 sub dsl { $_[0] }
45              
46             # exports new symbol to caller
47             sub export_symbols_to {
48 220     220 0 827 my ( $self, $caller, $args ) = @_;
49 220         1811 my $exports = $self->_construct_export_map($args);
50              
51             ## no critic
52 220         679 foreach my $export ( keys %{$exports} ) {
  220         2776  
53 143     143   1321 no strict 'refs'; ## no critic (TestingAndDebugging::ProhibitNoStrict)
  143         420  
  143         81945  
54 18044         25370 my $existing = *{"${caller}::${export}"}{CODE};
  18044         75415  
55              
56 18044 100       32576 next if defined $existing;
57              
58 17617         24198 *{"${caller}::${export}"} = $exports->{$export};
  17617         43548  
59             }
60             ## use critic
61              
62 220         2446 return keys %{$exports};
  220         23379325  
63             }
64              
65             # private
66              
67             sub _compile_keyword {
68 18044     18044   34601 my ( $self, $keyword, $opts ) = @_;
69              
70             my $code = $opts->{is_global}
71 916     916   28661745 ? sub { $self->$keyword(@_) }
72             : sub {
73 507 50   507   107000 croak "Function '$keyword' must be called from a route handler"
74             unless defined $Dancer2::Core::Route::REQUEST;
75              
76 507         3939 $self->$keyword(@_)
77 18044 100       79107 };
78              
79 18044         32660 return $self->_apply_prototype($code, $opts);
80             }
81              
82             sub _apply_prototype {
83 18044     18044   30169 my ($self, $code, $opts) = @_;
84              
85             # set prototype if one is defined for the keyword. undef => no prototype
86 18044         23064 my $prototype;
87 18044 100       33232 exists $opts->{'prototype'} and $prototype = $opts->{'prototype'};
88 18044         66950 return Scalar::Util::set_prototype( \&$code, $prototype );
89             }
90              
91             sub _construct_export_map {
92 220     220   654 my ( $self, $args ) = @_;
93 220         5166 my $keywords = $self->keywords;
94 220         7827 my %map;
95 220         3440 foreach my $keyword ( keys %$keywords ) {
96             # check if the keyword were excluded from importation
97 18049 100       41344 $args->{ '!' . $keyword } and next;
98 18044         36181 $map{$keyword} = $self->_compile_keyword( $keyword, $keywords->{$keyword} );
99             }
100 220         2928 return \%map;
101             }
102              
103             1;
104              
105             __END__