File Coverage

blib/lib/Text/MicroMason/LineNumbers.pm
Criterion Covered Total %
statement 41 45 91.1
branch 2 4 50.0
condition 7 14 50.0
subroutine 8 9 88.8
pod 7 7 100.0
total 65 79 82.2


line stmt bran cond sub pod time code
1             package Text::MicroMason::LineNumbers;
2 1     1   438 use strict;
  1         1  
  1         455  
3              
4             ######################################################################
5              
6             sub read {
7 9     9 1 5 my ( $self, $src_type, $src_data ) = @_;
8              
9 9         18 $self->{ last_read_file } = "unrecognized source $src_type";
10 9         9 $self->{ last_read_line } = 1;
11              
12 9         20 $self->NEXT( 'read', $src_type, $src_data )
13             }
14              
15             sub read_file {
16 2     2 1 3 my ( $self, $file ) = @_;
17              
18 2         2 $self->{ last_read_file } = $file;
19              
20 2         18 $self->NEXT( 'read_file', $file )
21             }
22              
23             sub read_handle {
24 0     0 1 0 my ( $self, $handle ) = @_;
25              
26 0         0 my ( $caller_file, $caller_line ) = $self->_get_external_caller();
27 0         0 $self->{ last_read_file } = "file handle template (compiled at $caller_file line $caller_line)";
28              
29 0         0 $self->NEXT( 'read_handle', $handle )
30             }
31              
32             sub read_text {
33 4     4 1 4 my ( $self, $text ) = @_;
34              
35 4         6 my ( $caller_file, $caller_line ) = $self->_get_external_caller();
36 4         9 $self->{ last_read_file } = "text template (compiled at $caller_file line $caller_line)";
37              
38 4         8 $self->NEXT( 'read_text', $text )
39             }
40              
41             sub read_inline {
42 3     3 1 2 my ( $self, $text ) = @_;
43              
44 3         8 my ( $caller_file, $caller_line ) = $self->_get_external_caller();
45 3         5 $self->{ last_read_file } = $caller_file;
46 3         2 $self->{ last_read_line } = $caller_line;
47              
48 3         5 $self->NEXT( 'read_text', $text )
49             }
50              
51             sub _get_external_caller {
52 7     7   5 my ( $self ) = @_;
53 7         4 my ( @caller, $call_level );
54 7   100     5 do { @caller = caller( ++ $call_level ) }
  45         315  
55             while ( $caller[0] =~ /^Text::MicroMason/ or $self->isa($caller[0]) );
56 7   33     20 return ( $caller[1] || $0, $caller[2] );
57             }
58              
59             ######################################################################
60              
61             sub lex {
62 9     9 1 9 my $self = shift;
63 9         11 local $_ = "$_[0]";
64            
65 9 50       21 my $lexer = $self->can('lex_token')
66             or $self->croak_msg('Unable to lex_token(); must select a syntax mixin');
67            
68 9   50     15 my $filename = $self->{ last_read_file } || 'unknown source';
69 9   50     14 my $linenum = $self->{ last_read_line } || 1;
70 9         4 my $last_pos = 0;
71            
72 9         7 my @tokens;
73 9         32 until ( /\G\z/gc ) {
74 26 50 0     42 my @parsed = &$lexer( $self )
75             or /\G ( .{0,20} ) /gcxs && die "MicroMason parsing halted at '$1'\n";
76 26         51 push @tokens, 'line_num' => ( $linenum - 1 ) . qq{ "$filename"};
77 26         22 push @tokens, @parsed;
78            
79             # Update the current line number by counting newlines in the text
80             # we've parsed since the last time through the loop.
81 26   50     38 my $new_pos = pos($_) || 0;
82 26         32 $linenum += ( substr($_, $last_pos, $new_pos - $last_pos) =~ tr[\n][] );
83 26         54 $last_pos = $new_pos;
84             }
85            
86 9         35 return @tokens;
87             }
88              
89             sub assembler_rules {
90 9     9 1 6 my $self = shift;
91             (
92 9         17 $self->NEXT('assembler_rules', @_),
93             line_num_token => 'perl # line TOKEN',
94             )
95             }
96              
97             ######################################################################
98              
99             1;
100              
101             ######################################################################
102              
103              
104             =head1 NAME
105              
106             Text::MicroMason::LineNumbers - Report errors at correct source code line numbers
107              
108              
109             =head1 DESCRIPTION
110              
111             This mixin class associates each token in a template with the line
112             number on which it was found, and then inserts special comments in the
113             generated Perl code that preserve that original source file and line
114             number information.
115              
116             This should facilitate debugging, by making it easier to match up run-
117             time errors with the template code that produced them.
118              
119             To turn this behavior on, just add "-LineNumbers" to your MicroMason
120             creation call:
121              
122             my $mason = Text::MicroMason->new( qw( -LineNumbers ) );
123              
124              
125             =head2 Public Methods
126              
127             These methods are called from within the normal flow of MicroMason
128             functionality, and you do not need to invoke them directly.
129              
130             =over 4
131              
132             =item read()
133              
134             Clears the variables used to store the file name and first line of a
135             template, so that they can be set by the methods below.
136              
137             =item read_file()
138              
139             Saves the source file name before invoking the standard behavior for this method.
140              
141             $mason->compile( file => $filename );
142              
143             =item read_handle()
144              
145             Saves the caller's file name before invoking the standard behavior for this method.
146              
147             $mason->compile( handle => $filename );
148              
149             =item read_text()
150              
151             Saves the caller's file name before invoking the standard behavior for this method.
152              
153             $mason->compile( text => $filename );
154              
155             =item read_inline()
156              
157             This is similar to read_text, except it adjusts the line numbering to
158             reflect a template that's embdded as a literal text in the Perl code.
159              
160             $mason->compile( inline => q{
161             My template text goes here.
162             } );
163              
164             =item lex()
165              
166             Identical to the lex() method provided by the Base class, except that it
167             also inserts a stream of line-number-setting comments into the to-be-
168             compiled Perl code that attempt to re-synchronize the
169              
170             =item assembler_rules()
171              
172             Maps the "line_num" token to a perl line number comment.
173              
174             =back
175              
176              
177             =head2 Private Methods
178              
179             =over 4
180              
181             =item _get_external_caller()
182              
183             Returns the source file and line number of the first item in the
184             function call stack that is not a Text::MicroMason package.
185              
186             =back
187              
188              
189             =head1 SEE ALSO
190              
191             For an overview of this templating framework, see L.
192              
193             This is a mixin class intended for use with L.
194              
195             For distribution, installation, support, copyright and license
196             information, see L.
197              
198             =cut
199