line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package indirect; |
2
|
|
|
|
|
|
|
|
3
|
15
|
|
|
15
|
|
174098
|
use 5.008_001; |
|
15
|
|
|
|
|
54
|
|
4
|
|
|
|
|
|
|
|
5
|
15
|
|
|
15
|
|
75
|
use strict; |
|
15
|
|
|
|
|
24
|
|
|
15
|
|
|
|
|
398
|
|
6
|
15
|
|
|
15
|
|
73
|
use warnings; |
|
15
|
|
|
|
|
25
|
|
|
15
|
|
|
|
|
1046
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
indirect - Lexically warn about using the indirect method call syntax. |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 VERSION |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Version 0.36 |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=cut |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
our $VERSION; |
19
|
|
|
|
|
|
|
BEGIN { |
20
|
15
|
|
|
15
|
|
2264
|
$VERSION = '0.36'; |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 SYNOPSIS |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
In a script : |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
no indirect; # lexically enables the pragma |
28
|
|
|
|
|
|
|
my $x = new Apple 1, 2, 3; # warns |
29
|
|
|
|
|
|
|
{ |
30
|
|
|
|
|
|
|
use indirect; # lexically disables the pragma |
31
|
|
|
|
|
|
|
my $y = new Pear; # legit, does not warn |
32
|
|
|
|
|
|
|
{ |
33
|
|
|
|
|
|
|
# lexically specify an hook called for each indirect construct |
34
|
|
|
|
|
|
|
no indirect hook => sub { |
35
|
|
|
|
|
|
|
die "You really wanted $_[0]\->$_[1] at $_[2]:$_[3]" |
36
|
|
|
|
|
|
|
}; |
37
|
|
|
|
|
|
|
my $z = new Pineapple 'fresh'; # croaks 'You really wanted...' |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
} |
40
|
|
|
|
|
|
|
try { ... }; # warns if try() hasn't been declared in this package |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
no indirect 'fatal'; # or ':fatal', 'FATAL', ':Fatal' ... |
43
|
|
|
|
|
|
|
if (defied $foo) { ... } # croaks, note the typo |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
Global uses : |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
# Globally enable the pragma from the command-line |
48
|
|
|
|
|
|
|
perl -M-indirect=global -e 'my $x = new Banana;' # warns |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# Globally enforce the pragma each time perl is executed |
51
|
|
|
|
|
|
|
export PERL5OPT="-M-indirect=global,fatal" |
52
|
|
|
|
|
|
|
perl -e 'my $y = new Coconut;' # croaks |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head1 DESCRIPTION |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
When enabled, this pragma warns about indirect method calls that are present in your code. |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
The indirect syntax is now considered harmful, since its parsing has many quirks and its use is error prone : when the subroutine C<foo> has not been declared in the current package, C<foo $x> actually compiles to C<< $x->foo >>, and C<< foo { key => 1 } >> to C<< 'key'->foo(1) >>. |
59
|
|
|
|
|
|
|
Please refer to the L</REFERENCES> section for a more complete list of reasons for avoiding this construct. |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
This pragma currently does not warn for core functions (C<print>, C<say>, C<exec> or C<system>). |
62
|
|
|
|
|
|
|
This may change in the future, or may be added as optional features that would be enabled by passing options to C<unimport>. |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
This module is B<not> a source filter. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=cut |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
BEGIN { |
69
|
15
|
100
|
|
15
|
|
81
|
if ($ENV{PERL_INDIRECT_PM_DISABLE}) { |
70
|
1
|
|
|
1
|
|
7
|
*_tag = sub ($) { 1 }; |
|
1
|
|
|
|
|
6
|
|
71
|
1
|
|
|
|
|
2
|
*I_THREADSAFE = sub () { 1 }; |
72
|
1
|
|
|
|
|
866
|
*I_FORKSAFE = sub () { 1 }; |
73
|
|
|
|
|
|
|
} else { |
74
|
14
|
|
|
|
|
76
|
require XSLoader; |
75
|
14
|
|
|
|
|
15355
|
XSLoader::load(__PACKAGE__, $VERSION); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=head1 METHODS |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=head2 C<unimport> |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
no indirect; |
84
|
|
|
|
|
|
|
no indirect 'fatal'; |
85
|
|
|
|
|
|
|
no indirect hook => sub { my ($obj, $name, $file, $line) = @_; ... }; |
86
|
|
|
|
|
|
|
no indirect 'global'; |
87
|
|
|
|
|
|
|
no indirect 'global, 'fatal'; |
88
|
|
|
|
|
|
|
no indirect 'global', hook => sub { ... }; |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
Magically called when C<no indirect @opts> is encountered. |
91
|
|
|
|
|
|
|
Turns the module on. |
92
|
|
|
|
|
|
|
The policy to apply depends on what is first found in C<@opts> : |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=over 4 |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=item * |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
If it is a string that matches C</^:?fatal$/i>, the compilation will croak when the first indirect method call is found. |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
This option is mutually exclusive with the C<'hook'> option. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=item * |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
If the key/value pair C<< hook => $hook >> comes first, C<$hook> will be called for each error with a string representation of the object as C<$_[0]>, the method name as C<$_[1]>, the current file as C<$_[2]> and the line number as C<$_[3]>. |
105
|
|
|
|
|
|
|
If and only if the object is actually a block, C<$_[0]> is assured to start by C<'{'>. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
This option is mutually exclusive with the C<'fatal'> option. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=item * |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
If none of C<fatal> and C<hook> are specified, a warning will be emitted for each indirect method call. |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=item * |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
If C<@opts> contains a string that matches C</^:?global$/i>, the pragma will be globally enabled for B<all> code compiled after the current C<no indirect> statement, except for code that is in the lexical scope of C<use indirect>. |
116
|
|
|
|
|
|
|
This option may come indifferently before or after the C<fatal> or C<hook> options, in the case they are also passed to L</unimport>. |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
The global policy applied is the one resulting of the C<fatal> or C<hook> options, thus defaults to a warning when none of those are specified : |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
no indirect 'global'; # warn for any indirect call |
121
|
|
|
|
|
|
|
no indirect qw<global fatal>; # die on any indirect call |
122
|
|
|
|
|
|
|
no indirect 'global', hook => \&hook # custom global action |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
Note that if another policy is installed by a C<no indirect> statement further in the code, it will overrule the global policy : |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
no indirect 'global'; # warn globally |
127
|
|
|
|
|
|
|
{ |
128
|
|
|
|
|
|
|
no indirect 'fatal'; # throw exceptions for this lexical scope |
129
|
|
|
|
|
|
|
... |
130
|
|
|
|
|
|
|
require Some::Module; # the global policy will apply for the |
131
|
|
|
|
|
|
|
# compilation phase of this module |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=back |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=cut |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub _no_hook_and_fatal { |
139
|
2
|
|
|
2
|
|
15
|
require Carp; |
140
|
2
|
|
|
|
|
404
|
Carp::croak("The 'fatal' and 'hook' options are mutually exclusive"); |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub unimport { |
144
|
3070
|
|
|
3070
|
|
1022838
|
shift; |
145
|
|
|
|
|
|
|
|
146
|
3070
|
|
|
|
|
3590
|
my ($global, $fatal, $hook); |
147
|
|
|
|
|
|
|
|
148
|
3070
|
|
|
|
|
8139
|
while (@_) { |
149
|
1047
|
|
|
|
|
1194
|
my $arg = shift; |
150
|
1047
|
100
|
|
|
|
2314
|
if ($arg eq 'hook') { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
151
|
1023
|
100
|
|
|
|
1593
|
_no_hook_and_fatal() if $fatal; |
152
|
1022
|
|
|
|
|
2163
|
$hook = shift; |
153
|
|
|
|
|
|
|
} elsif ($arg =~ /^:?fatal$/i) { |
154
|
17
|
100
|
|
|
|
50
|
_no_hook_and_fatal() if defined $hook; |
155
|
16
|
|
|
|
|
73
|
$fatal = 1; |
156
|
|
|
|
|
|
|
} elsif ($arg =~ /^:?global$/i) { |
157
|
5
|
|
|
|
|
12
|
$global = 1; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
3068
|
100
|
|
|
|
6042
|
unless (defined $hook) { |
162
|
2047
|
100
|
|
7
|
|
10851
|
$hook = $fatal ? sub { die msg(@_) } : sub { warn msg(@_) }; |
|
7
|
|
|
|
|
23
|
|
|
332
|
|
|
|
|
26730
|
|
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
3068
|
|
|
|
|
6640
|
$^H |= 0x00020000; |
166
|
3068
|
100
|
|
|
|
4641
|
if ($global) { |
167
|
5
|
|
|
|
|
26
|
delete $^H{+(__PACKAGE__)}; |
168
|
5
|
|
|
|
|
25
|
_global($hook); |
169
|
|
|
|
|
|
|
} else { |
170
|
3063
|
|
|
|
|
13796
|
$^H{+(__PACKAGE__)} = _tag($hook); |
171
|
|
|
|
|
|
|
} |
172
|
|
|
|
|
|
|
|
173
|
3068
|
|
|
|
|
209384
|
return; |
174
|
|
|
|
|
|
|
} |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=head2 C<import> |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
use indirect; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
Magically called at each C<use indirect>. Turns the module off. |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
As explained in L</unimport>'s description, an C<use indirect> statement will lexically override a global policy previously installed by C<no indirect 'global', ...> (if there's one). |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=cut |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub import { |
187
|
2023
|
|
|
2023
|
|
1016174
|
$^H |= 0x00020000; |
188
|
2023
|
|
|
|
|
7677
|
$^H{+(__PACKAGE__)} = _tag(undef); |
189
|
|
|
|
|
|
|
|
190
|
2023
|
|
|
|
|
126041
|
return; |
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=head1 FUNCTIONS |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head2 C<msg> |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
my $msg = msg($object, $method, $file, $line); |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
Returns the default error message that C<indirect> generates when an indirect method call is reported. |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
=cut |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub msg { |
204
|
340
|
|
|
340
|
1
|
523
|
my $obj = $_[0]; |
205
|
|
|
|
|
|
|
|
206
|
340
|
100
|
|
|
|
5110
|
join ' ', "Indirect call of method \"$_[1]\" on", |
207
|
|
|
|
|
|
|
($obj =~ /^\s*\{/ ? "a block" : "object \"$obj\""), |
208
|
|
|
|
|
|
|
"at $_[2] line $_[3].\n"; |
209
|
|
|
|
|
|
|
}; |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=head1 CONSTANTS |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=head2 C<I_THREADSAFE> |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
True iff the module could have been built with thread-safety features enabled. |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
=head2 C<I_FORKSAFE> |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
True iff this module could have been built with fork-safety features enabled. |
220
|
|
|
|
|
|
|
This will always be true except on Windows where it's false for perl 5.10.0 and below . |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=head1 DIAGNOSTICS |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=head2 C<Indirect call of method "%s" on object "%s" at %s line %d.> |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
The default warning/exception message thrown when an indirect method call on an object is found. |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
=head2 C<Indirect call of method "%s" on a block at %s line %d.> |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
The default warning/exception message thrown when an indirect method call on a block is found. |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=head1 ENVIRONMENT |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=head2 C<PERL_INDIRECT_PM_DISABLE> |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
If this environment variable is set to true when the pragma is used for the first time, the XS code won't be loaded and, although the C<'indirect'> lexical hint will be set to true in the scope of use, the pragma itself won't do anything. |
237
|
|
|
|
|
|
|
In this case, the pragma will always be considered to be thread-safe, and as such L</I_THREADSAFE> will be true. |
238
|
|
|
|
|
|
|
This is useful for disabling C<indirect> in production environments. |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Note that clearing this variable after C<indirect> was loaded has no effect. |
241
|
|
|
|
|
|
|
If you want to re-enable the pragma later, you also need to reload it by deleting the C<'indirect.pm'> entry from C<%INC>. |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=head1 CAVEATS |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
The implementation was tweaked to work around several limitations of vanilla C<perl> pragmas : it's thread safe, and does not suffer from a C<perl 5.8.x-5.10.0> bug that causes all pragmas to propagate into C<require>d scopes. |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
Before C<perl> 5.12, C<meth $obj> (no semicolon) at the end of a file is not seen as an indirect method call, although it is as soon as there is another token before the end (as in C<meth $obj;> or C<meth $obj 1>). |
248
|
|
|
|
|
|
|
If you use C<perl> 5.12 or greater, those constructs are correctly reported. |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
With 5.8 perls, the pragma does not propagate into C<eval STRING>. |
251
|
|
|
|
|
|
|
This is due to a shortcoming in the way perl handles the hints hash, which is addressed in perl 5.10. |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
The search for indirect method calls happens before constant folding. |
254
|
|
|
|
|
|
|
Hence C<my $x = new Class if 0> will be caught. |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=head1 REFERENCES |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
Numerous articles have been written about the quirks of the indirect object construct : |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
=over 4 |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=item * |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
L<http://markmail.org/message/o7d5sxnydya7bwvv> : B<Far More Than Everything You've Ever Wanted to Know about the Indirect Object syntax>, Tom Christiansen, 1998-01-28. |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
This historical post to the C<perl5-porters> mailing list raised awareness about the perils of this syntax. |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=item * |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
L<http://www.shadowcat.co.uk/blog/matt-s-trout/indirect-but-still-fatal> : B<Indirect but still fatal>, Matt S. Trout, 2009-07-29. |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
In this blog post, the author gives an example of an undesirable indirect method call on a block that causes a particularly bewildering error. |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=back |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
L<perl> 5.8.1. |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
A C compiler. |
281
|
|
|
|
|
|
|
This module may happen to build with a C++ compiler as well, but don't rely on it, as no guarantee is made in this regard. |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
L<Carp> (standard since perl 5), L<XSLoader> (since perl 5.6.0). |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=head1 AUTHOR |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>. |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
You can contact me by mail or on C<irc.perl.org> (vincent). |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=head1 BUGS |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
Please report any bugs or feature requests to C<bug-indirect at rt.cpan.org>, or through the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=indirect>. |
294
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head1 SUPPORT |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
perldoc indirect |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
Tests code coverage report is available at L<http://www.profvince.com/perl/cover/indirect>. |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
Bram, for motivation and advices. |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
Andrew Main and Florian Ragwitz, for testing on real-life code and reporting issues. |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
Copyright 2008,2009,2010,2011,2012,2013,2014,2015 Vincent Pit, all rights reserved. |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
=cut |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
1; # End of indirect |