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.1.0';
4 146     146   452786 use Moo::Role;
  146         20554  
  146         1254  
5 146     146   84485 use Dancer2::Core::Types;
  146         528  
  146         1578  
6 146     146   2172904 use Carp 'croak';
  146         401  
  146         11997  
7 146     146   1087 use Scalar::Util qw();
  146         359  
  146         64657  
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 225     225   2434 my ($self) = @_;
22 225 50       2343 $self->can('dsl_keywords')
23             ? $self->dsl_keywords
24             : {};
25             }
26              
27             sub register {
28 2     2 0 42 my ( $self, $keyword, $is_global ) = @_;
29 2         56 my $keywords = $self->keywords;
30 2         78 my $pkg = ref($self);
31 2         9 $pkg =~ s/__WITH__.+$//;
32              
33 2 50       11 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         22 $keywords->{$keyword} = { is_global => $is_global, pkg => $pkg };
42             }
43              
44 19     19 0 147 sub dsl { $_[0] }
45              
46             # exports new symbol to caller
47             sub export_symbols_to {
48 225     225 0 840 my ( $self, $caller, $args ) = @_;
49 225         1047 my $exports = $self->_construct_export_map($args);
50              
51             ## no critic
52 225         671 foreach my $export ( keys %{$exports} ) {
  225         2911  
53 146     146   1239 no strict 'refs'; ## no critic (TestingAndDebugging::ProhibitNoStrict)
  146         451  
  146         80984  
54 18454         24225 my $existing = *{"${caller}::${export}"}{CODE};
  18454         65085  
55              
56 18454 100       44733 next if defined $existing;
57              
58 18026         25926 *{"${caller}::${export}"} = $exports->{$export};
  18026         41433  
59             }
60             ## use critic
61              
62 225         2437 return keys %{$exports};
  225         22703077  
63             }
64              
65             # private
66              
67             sub _compile_keyword {
68 18454     18454   32989 my ( $self, $keyword, $opts ) = @_;
69              
70             my $code = $opts->{is_global}
71 921     921   29484181 ? sub { $self->$keyword(@_) }
72             : sub {
73 511 50   511   109597 croak "Function '$keyword' must be called from a route handler"
74             unless defined $Dancer2::Core::Route::REQUEST;
75              
76 511         3342 $self->$keyword(@_)
77 18454 100       79567 };
78              
79 18454         34540 return $self->_apply_prototype($code, $opts);
80             }
81              
82             sub _apply_prototype {
83 18454     18454   30601 my ($self, $code, $opts) = @_;
84              
85             # set prototype if one is defined for the keyword. undef => no prototype
86 18454         24259 my $prototype;
87 18454 100       35684 exists $opts->{'prototype'} and $prototype = $opts->{'prototype'};
88 18454         69710 return Scalar::Util::set_prototype( \&$code, $prototype );
89             }
90              
91             sub _construct_export_map {
92 225     225   716 my ( $self, $args ) = @_;
93 225         5179 my $keywords = $self->keywords;
94 225         7491 my %map;
95 225         3452 foreach my $keyword ( keys %$keywords ) {
96             # check if the keyword were excluded from importation
97 18459 100       42162 $args->{ '!' . $keyword } and next;
98 18454         34943 $map{$keyword} = $self->_compile_keyword( $keyword, $keywords->{$keyword} );
99             }
100 225         2789 return \%map;
101             }
102              
103             1;
104              
105             __END__