File Coverage

blib/lib/MooseX/Declare/Syntax/KeywordHandling.pm
Criterion Covered Total %
statement 44 44 100.0
branch 6 6 100.0
condition 2 2 100.0
subroutine 15 15 100.0
pod 3 5 60.0
total 70 72 97.2


line stmt bran cond sub pod time code
1             package MooseX::Declare::Syntax::KeywordHandling;
2             # ABSTRACT: Basic keyword functionality
3              
4             our $VERSION = '0.43';
5              
6 24     24   14918 use Moose::Role;
  24         41  
  24         181  
7 24     24   88368 use Moose::Util::TypeConstraints qw(subtype as where);
  24         41  
  24         202  
8 24     24   9814 use Devel::Declare ();
  24         39  
  24         486  
9 24     24   96 use Sub::Install qw( install_sub );
  24         28  
  24         221  
10 24     24   1662 use Moose::Meta::Class ();
  24         33  
  24         400  
11 24     24   85 use Module::Runtime 'use_module';
  24         30  
  24         146  
12              
13 24     24   915 use aliased 'MooseX::Declare::Context';
  24         31  
  24         175  
14              
15 24     24   2670 use namespace::autoclean -also => ['_uniq'];
  24         32  
  24         292  
16              
17             #pod =head1 DESCRIPTION
18             #pod
19             #pod This role provides the functionality common for all keyword handlers
20             #pod in L<MooseX::Declare>.
21             #pod
22             #pod =head1 REQUIRED METHODS
23             #pod
24             #pod =head2 parse
25             #pod
26             #pod Object->parse (Object $context)
27             #pod
28             #pod This method must implement the actual parsing of the keyword syntax.
29             #pod
30             #pod =cut
31              
32             requires qw(
33             parse
34             );
35              
36             #pod =attr identifier
37             #pod
38             #pod This is the name of the actual keyword. It is a required string that is in
39             #pod the same format as a usual Perl identifier.
40             #pod
41             #pod =cut
42              
43             has identifier => (
44             is => 'ro',
45             isa => subtype(as 'Str', where { /^ [_a-z] [_a-z0-9]* $/ix }),
46             required => 1,
47             );
48              
49             #pod =method get_identifier
50             #pod
51             #pod Str Object->get_identifier ()
52             #pod
53             #pod Returns the name the handler will be setup under.
54             #pod
55             #pod =cut
56              
57 879     879 1 29016 sub get_identifier { shift->identifier }
58              
59 129     129 0 301 sub context_class { Context }
60              
61       66 0   sub context_traits { }
62              
63             #pod =method setup_for
64             #pod
65             #pod Object->setup_for (ClassName $class, %args)
66             #pod
67             #pod This will setup the handler in the specified C<$class>. The handler will
68             #pod dispatch to the L</parse_declaration> method when the keyword is used.
69             #pod
70             #pod A normal code reference will also be exported into the calling namespace.
71             #pod It will either be empty or, if a C<generate_export> method is provided,
72             #pod the return value of that method.
73             #pod
74             #pod =cut
75              
76             sub setup_for {
77 749     749 1 4294 my ($self, $setup_class, %args) = @_;
78              
79             # make sure the stack is valid
80 749   100     1981 my $stack = $args{stack} || [];
81 749         2290 my $ident = $self->get_identifier;
82              
83             # setup the D:D handler for our keyword
84             Devel::Declare->setup_for($setup_class, {
85             $ident => {
86 129     129   2423780 const => sub { $self->parse_declaration((caller(1))[1], \%args, @_) },
87             },
88 749         6396 });
89              
90             # search or generate a real export
91 749 100   5   16573 my $export = $self->can('generate_export') ? $self->generate_export($setup_class) : sub { };
92              
93             # export subroutine
94 749 100       7466 install_sub({
95             code => $export,
96             into => $setup_class,
97             as => $ident,
98             }) unless $setup_class->can($ident);
99              
100 749         44827 return 1;
101             }
102              
103             #pod =method parse_declaration
104             #pod
105             #pod Object->parse_declaration (Str $filename, HashRef $setup_args, @call_args)
106             #pod
107             #pod This simply creates a new L<context|MooseX::Declare::Context> and passes it
108             #pod to the L</parse> method.
109             #pod
110             #pod =cut
111              
112             sub parse_declaration {
113 129     129 1 403 my ($self, $caller_file, $args, @ctx_args) = @_;
114              
115             # find and load context object class
116 129         490 my $ctx_class = $self->context_class;
117 129         613 use_module $ctx_class;
118              
119             # do we have traits?
120 129 100       4321 if (my @ctx_traits = _uniq($self->context_traits)) {
121              
122             use_module $_
123 73         281 for @ctx_traits;
124              
125 73         2979 $ctx_class = Moose::Meta::Class->create_anon_class(
126             superclasses => [$ctx_class],
127             roles => [@ctx_traits],
128             cache => 1,
129             )->name;
130             }
131              
132             # create a context object and initialize it
133             my $ctx = $ctx_class->new(
134 129         37556 %{ $args },
  129         1498  
135             caller_file => $caller_file,
136             );
137 129         1624 $ctx->init(@ctx_args);
138              
139             # parse with current context
140 129         2776 return $self->parse($ctx);
141             }
142              
143             sub _uniq { keys %{ +{ map { $_ => undef } @_ } } }
144              
145             #pod =head1 SEE ALSO
146             #pod
147             #pod =for :list
148             #pod * L<MooseX::Declare>
149             #pod * L<MooseX::Declare::Context>
150             #pod
151             #pod =cut
152              
153             1;
154              
155             __END__
156              
157             =pod
158              
159             =encoding UTF-8
160              
161             =head1 NAME
162              
163             MooseX::Declare::Syntax::KeywordHandling - Basic keyword functionality
164              
165             =head1 VERSION
166              
167             version 0.43
168              
169             =head1 DESCRIPTION
170              
171             This role provides the functionality common for all keyword handlers
172             in L<MooseX::Declare>.
173              
174             =head1 ATTRIBUTES
175              
176             =head2 identifier
177              
178             This is the name of the actual keyword. It is a required string that is in
179             the same format as a usual Perl identifier.
180              
181             =head1 METHODS
182              
183             =head2 get_identifier
184              
185             Str Object->get_identifier ()
186              
187             Returns the name the handler will be setup under.
188              
189             =head2 setup_for
190              
191             Object->setup_for (ClassName $class, %args)
192              
193             This will setup the handler in the specified C<$class>. The handler will
194             dispatch to the L</parse_declaration> method when the keyword is used.
195              
196             A normal code reference will also be exported into the calling namespace.
197             It will either be empty or, if a C<generate_export> method is provided,
198             the return value of that method.
199              
200             =head2 parse_declaration
201              
202             Object->parse_declaration (Str $filename, HashRef $setup_args, @call_args)
203              
204             This simply creates a new L<context|MooseX::Declare::Context> and passes it
205             to the L</parse> method.
206              
207             =head1 REQUIRED METHODS
208              
209             =head2 parse
210              
211             Object->parse (Object $context)
212              
213             This method must implement the actual parsing of the keyword syntax.
214              
215             =head1 SEE ALSO
216              
217             =over 4
218              
219             =item *
220              
221             L<MooseX::Declare>
222              
223             =item *
224              
225             L<MooseX::Declare::Context>
226              
227             =back
228              
229             =head1 AUTHOR
230              
231             Florian Ragwitz <rafl@debian.org>
232              
233             =head1 COPYRIGHT AND LICENSE
234              
235             This software is copyright (c) 2008 by Florian Ragwitz.
236              
237             This is free software; you can redistribute it and/or modify it under
238             the same terms as the Perl 5 programming language system itself.
239              
240             =cut