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 15 15 100.0
pod 0 3 0.0
total 78 90 86.6


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 = '0.400001';
4 137     137   89992 use Moo::Role;
  137         382  
  137         1042  
5 137     137   63235 use Dancer2::Core::Types;
  137         393  
  137         1099  
6 137     137   1746123 use Carp 'croak';
  137         356  
  137         8161  
7 137     137   1003 use Scalar::Util qw();
  137         352  
  137         48201  
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 210     210   1998 my ($self) = @_;
22 210 50       1613 $self->can('dsl_keywords')
23             ? $self->dsl_keywords
24             : {};
25             }
26              
27             sub register {
28 2     2 0 34 my ( $self, $keyword, $is_global ) = @_;
29 2         40 my $keywords = $self->keywords;
30 2         62 my $pkg = ref($self);
31 2         5 $pkg =~ s/__WITH__.+$//;
32              
33 2 50       9 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         15 $keywords->{$keyword} = { is_global => $is_global, pkg => $pkg };
42             }
43              
44 29     29 0 81 sub dsl { $_[0] }
45              
46             # exports new symbol to caller
47             sub export_symbols_to {
48 210     210 0 712 my ( $self, $caller, $args ) = @_;
49 210         758 my $exports = $self->_construct_export_map($args);
50              
51             ## no critic
52 210         554 foreach my $export ( keys %{$exports} ) {
  210         2822  
53 137     137   1154 no strict 'refs'; ## no critic (TestingAndDebugging::ProhibitNoStrict)
  137         365  
  137         56109  
54 17014         20547 my $existing = *{"${caller}::${export}"}{CODE};
  17014         50057  
55              
56 17014 100       29704 next if defined $existing;
57              
58 16592         20967 *{"${caller}::${export}"} = $exports->{$export};
  16592         34945  
59             }
60             ## use critic
61              
62 210         1278 return keys %{$exports};
  210         18829254  
63             }
64              
65             # private
66              
67             sub _compile_keyword {
68 17014     17014   26972 my ( $self, $keyword, $opts ) = @_;
69              
70             my $code = $opts->{is_global}
71 849     849   359719 ? sub { $self->$keyword(@_) }
        819      
72             : sub {
73 472 50   472   74595 croak "Function '$keyword' must be called from a route handler"
74             unless defined $Dancer2::Core::Route::REQUEST;
75              
76 472         2291 $self->$keyword(@_)
77 17014 100       63340 };
78              
79 17014         32021 return $self->_apply_prototype($code, $opts);
80             }
81              
82             sub _apply_prototype {
83 17014     17014   24879 my ($self, $code, $opts) = @_;
84              
85             # set prototype if one is defined for the keyword. undef => no prototype
86 17014         19976 my $prototype;
87 17014 100       28419 exists $opts->{'prototype'} and $prototype = $opts->{'prototype'};
88 17014         57342 return Scalar::Util::set_prototype( \&$code, $prototype );
89             }
90              
91             sub _construct_export_map {
92 210     210   506 my ( $self, $args ) = @_;
93 210         3574 my $keywords = $self->keywords;
94 210         5780 my %map;
95 210         2809 foreach my $keyword ( keys %$keywords ) {
96             # check if the keyword were excluded from importation
97 17019 100       36917 $args->{ '!' . $keyword } and next;
98 17014         27164 $map{$keyword} = $self->_compile_keyword( $keyword, $keywords->{$keyword} );
99             }
100 210         1601 return \%map;
101             }
102              
103             1;
104              
105             __END__
106              
107             =pod
108              
109             =encoding UTF-8
110              
111             =head1 NAME
112              
113             Dancer2::Core::Role::DSL - Role for DSL
114              
115             =head1 VERSION
116              
117             version 0.400001
118              
119             =head1 AUTHOR
120              
121             Dancer Core Developers
122              
123             =head1 COPYRIGHT AND LICENSE
124              
125             This software is copyright (c) 2023 by Alexis Sukrieh.
126              
127             This is free software; you can redistribute it and/or modify it under
128             the same terms as the Perl 5 programming language system itself.
129              
130             =cut