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
|
|
|
|
|
|
|
|