File Coverage

blib/lib/Method/Signatures/WithDocumentation.pm
Criterion Covered Total %
statement 61 62 98.3
branch 1 2 50.0
condition 1 3 33.3
subroutine 26 27 96.3
pod 0 10 0.0
total 89 104 85.5


line stmt bran cond sub pod time code
1 2     2   3042 use strictures 2;
  2         2174  
  2         76  
2              
3             package Method::Signatures::WithDocumentation;
4              
5             # ABSTRACT: use Method::Signatures with Sub::Documentation together
6              
7 2     2   1360 use Attribute::Handlers;
  2         6781  
  2         10  
8 2     2   59 use Sub::Documentation 'add_documentation';
  2         2  
  2         86  
9 2     2   1131 use Moose;
  2         651699  
  2         16  
10 2     2   11637 use Data::Alias;
  2         1660  
  2         921  
11             extends 'Method::Signatures';
12              
13             our $VERSION = '1.000'; # VERSION
14              
15             around parse_proto => sub {
16             my ($orig, $self, @args) = @_;
17             my $code = $self->$orig(@args);
18             return $code unless $self->{function_name};
19             my $signature = $self->{signature};
20             my @parameters = @{ $signature->parameters };
21             my @short_sig;
22             foreach my $parameter (@parameters) {
23             if ($parameter->is_yadayada) {
24             push @short_sig => '...';
25             next;
26             }
27             my @doc = ($parameter->type, $parameter->variable);
28             push @doc => 'named' if $parameter->is_named;
29             push @doc => 'aliased' if $parameter->is_ref_alias;
30             push @doc => 'required' if $parameter->is_required;
31             push @doc => 'optional' if not $parameter->is_required;
32             push @doc => 'defaults to C<<< '.$parameter->default.' >>>' if $parameter->default;
33             push @doc => 'but only when C<<< '.$parameter->default_when.' >>>' if $parameter->default_when;
34              
35             my $short_sig = $parameter->type . ' ';
36             $short_sig .= "\\" if $parameter->is_ref_alias;
37             $short_sig = $parameter->variable_name.' => '.$short_sig if $parameter->is_named;
38             $short_sig .= $parameter->variable;
39             $short_sig = "[ $short_sig ]" unless $parameter->is_required;
40              
41             add_documentation(
42             package => $self->{into},
43             glob_type => 'CODE',
44             name => $self->{function_name},
45             type => 'param_signature',
46             documentation => \@doc,
47             );
48             push @short_sig => $short_sig;
49             }
50             add_documentation(
51             package => $self->{into},
52             glob_type => 'CODE',
53             name => $self->{function_name},
54             type => 'type',
55             documentation => $self->{name},
56             );
57             add_documentation(
58             package => $self->{into},
59             glob_type => 'CODE',
60             name => $self->{function_name},
61             type => 'signature',
62             documentation => join(', ', @short_sig),
63             );
64             return $code;
65             };
66              
67             sub _add_attr_doc {
68 57     57   77 my ($type, $package, $symbol, $referent, $data) = @_[0..3,5];
69 57 50 33     90 $data = $data->[0] if ref($data) eq 'ARRAY' && @$data == 1;
70 57         106 add_documentation(
71             package => $package,
72             glob_type => ref($referent),
73 57         41 name => *{$symbol}{NAME},
74             type => $type,
75             documentation => $data,
76             );
77             }
78              
79              
80 2     2   10 no warnings 'redefine'; ## no critic
  2         2  
  2         119  
81              
82              
83             sub UNIVERSAL::Name : ATTR(CODE,BEGIN,RAWDATA) {
84 0     0 0 0 _add_attr_doc(name => @_);
85 2     2   9 }
  2         2  
  2         14  
86              
87              
88             sub UNIVERSAL::Purpose : ATTR(CODE,BEGIN,RAWDATA) {
89 5     5 0 2858 _add_attr_doc(purpose => @_);
90 2     2   845 }
  2         3  
  2         8  
91              
92              
93             sub UNIVERSAL::Pod : ATTR(CODE,BEGIN,RAWDATA) {
94 8     8 0 297 _add_attr_doc(pod => @_);
95 2     2   651 }
  2         4  
  2         7  
96              
97              
98             sub UNIVERSAL::Param : ATTR(CODE,BEGIN,RAWDATA) {
99 12     12 0 461 _add_attr_doc(param => @_);
100 2     2   612 }
  2         4  
  2         8  
101              
102              
103             sub UNIVERSAL::Author : ATTR(CODE,BEGIN,RAWDATA) {
104 8     8 0 301 _add_attr_doc(author => @_);
105 2     2   522 }
  2         4  
  2         6  
106              
107              
108             sub UNIVERSAL::Returns : ATTR(CODE,BEGIN,RAWDATA) {
109 4     4 0 156 _add_attr_doc(returns => @_);
110 2     2   529 }
  2         3  
  2         12  
111              
112              
113             sub UNIVERSAL::Throws : ATTR(CODE,BEGIN,RAWDATA) {
114 8     8 0 303 _add_attr_doc(throws => @_);
115 2     2   472 }
  2         4  
  2         6  
116              
117              
118             sub UNIVERSAL::Example : ATTR(CODE,BEGIN,RAWDATA) {
119 4     4 0 194 _add_attr_doc(example => @_);
120 2     2   530 }
  2         4  
  2         5  
121              
122              
123             sub UNIVERSAL::Since : ATTR(CODE,BEGIN,RAWDATA) {
124 4     4 0 153 _add_attr_doc(since => @_);
125 2     2   469 }
  2         3  
  2         7  
126              
127              
128             sub UNIVERSAL::Deprecated : ATTR(CODE,BEGIN,RAWDATA) {
129 4     4 0 159 _add_attr_doc(deprecated => @_);
130 2     2   506 }
  2         4  
  2         4  
131              
132             1;
133              
134             __END__
135              
136             =pod
137              
138             =head1 NAME
139              
140             Method::Signatures::WithDocumentation - use Method::Signatures with Sub::Documentation together
141              
142             =head1 VERSION
143              
144             version 1.000
145              
146             =head1 SYNOPSIS
147              
148             use Method::Signatures::WithDocumentation;
149            
150             method foo (Str $text) :Purpose(Does something with text) {
151             ...
152             }
153              
154             =head1 DESCRIPTION
155              
156             This module extends L<Method::Signatures> to grab out parameter definitions. It behaves also similiar to L<Sub::Documentation::Attributes>, but with an important fix to let it work together with L<Pod::Weaver::Section::AutoDoc>.
157              
158             =head1 SUBROUTINE ATTRIBUTES
159              
160             Each of the attributes (except C<Deprecated>) requires a non-interpolated string. B<Please note that all parantheses must be balanced>.
161              
162             =head2 Name
163              
164             Use another name instead of method/function for documentation.
165              
166             =head2 Purpose
167              
168             A brief description what the function/method does.
169              
170             =head2 Pod
171              
172             Free-text deeper description of whats going on.
173              
174             =head2 Param
175              
176             A description of a function/method param, suggested by the following format:
177              
178             method xxx ($foo, $bar) :Param($foo: This is foo) :Param($bar: This is bar) { ... }
179              
180             Just the variable name (without modifiers like C<\>, C<:>, C<?> or C<!>) followed by a colon and the description.
181              
182             =head2 Author
183              
184             Name of the author of the method/function, if it differs from the module author and the name should be explicity printed in the documentation.
185              
186             Maybe used more than once, one for each author.
187              
188             =head2 Returns
189              
190             A free text what will be returned.
191              
192             =head2 Throws
193              
194             A free text what will be thrown in case of whatever.
195              
196             Maybe used more than once, one for each case.
197              
198             =head2 Example
199              
200             A verbatim text, like a synopsis at the beginning of each module documentation.
201              
202             =head2 Since
203              
204             An identifier since when the method/function is available. For example a date or a version number.
205              
206             =head2 Deprecated
207              
208             This attributes marks the method/function as deprecated. The reason is optional.
209              
210             =head1 SEE ALSO
211              
212             =for :list * L<Pod::Weaver::Section::AutoDoc>
213              
214             =head1 FORMATTING TIPS
215              
216             For some readers it might be confusing the read a subroutine definition with many attributes. There is no best practise at the moment, but I suggest this template:
217              
218             func foobar (Int $amount = 1) :
219             Purpose(
220             Prints out I<foo> and I<bar>
221             )
222             Example(
223             foobar(2); # prints two foos and two bars
224             )
225             Param(
226             $amount: how many foo and bar should be printed
227             )
228             Pod(
229             This function is an example to show you a fancy way for its documentation
230             )
231             Returns(
232             True on success
233             )
234             Throws(
235             An error message if there is no output device
236             )
237             Since(
238             1.000
239             )
240             Deprecated(
241             Use L</foobar_v2> instead.
242             )
243             Author(
244             John Doe
245             )
246             { ... }
247              
248             =head1 BUGS
249              
250             Please report any bugs or feature requests on the bugtracker website
251             https://github.com/zurborg/libmethod-signatures-withdocumentation-perl/issu
252             es
253              
254             When submitting a bug or request, please include a test-file or a
255             patch to an existing test-file that illustrates the bug or desired
256             feature.
257              
258             =head1 AUTHOR
259              
260             David Zurborg <zurborg@cpan.org>
261              
262             =head1 COPYRIGHT AND LICENSE
263              
264             This software is Copyright (c) 2015 by David Zurborg.
265              
266             This is free software, licensed under:
267              
268             The ISC License
269              
270             =cut