use 5.006;
use Carp;
use warnings;
-$VERSION = '0.78_03';
+$VERSION = '0.78_04';
# $DB::single=1;
my %symcache;
return sub {
_resolve_lastattr;
my ($pkg, $ref, @attrs) = @_;
+ my (undef, $filename, $linenum) = caller 2;
foreach (@attrs) {
my ($attr, $data) = /^([a-z_]\w*)(?:[(](.*)[)])?$/is or next;
if ($attr eq 'ATTR') {
my $handler = $pkg->can("_ATTR_${type}_${attr}");
next unless $handler;
my $decl = [$pkg, $ref, $attr, $data,
- $raw{$handler}, $phase{$handler}];
+ $raw{$handler}, $phase{$handler}, $filename, $linenum];
foreach my $gphase (@global_phases) {
_apply_handler_AH_($decl,$gphase)
if $global_phases{$gphase} <= $global_phase;
sub _apply_handler_AH_ {
my ($declaration, $phase) = @_;
- my ($pkg, $ref, $attr, $data, $raw, $handlerphase) = @$declaration;
+ my ($pkg, $ref, $attr, $data, $raw, $handlerphase, $filename, $linenum) = @$declaration;
return unless $handlerphase->{$phase};
# print STDERR "Handling $attr on $ref in $phase with [$data]\n";
my $type = ref $ref;
$attr,
(@$data>1? $data : $data->[0]),
$phase,
+ $filename,
+ $linenum,
);
return 1;
}
the desired attribute, and declare the subroutine itself with the
attribute C<:ATTR>. For example:
- package LoudDecl;
- use Attribute::Handlers;
-
- sub Loud :ATTR {
- my ($package, $symbol, $referent, $attr, $data, $phase) = @_;
- print STDERR
- ref($referent), " ",
- *{$symbol}{NAME}, " ",
- "($referent) ", "was just declared ",
- "and ascribed the ${attr} attribute ",
- "with data ($data)\n",
- "in phase $phase\n";
- }
+ package LoudDecl;
+ use Attribute::Handlers;
+
+ sub Loud :ATTR {
+ my ($package, $symbol, $referent, $attr, $data, $phase, $filename, $linenum) = @_;
+ print STDERR
+ ref($referent), " ",
+ *{$symbol}{NAME}, " ",
+ "($referent) ", "was just declared ",
+ "and ascribed the ${attr} attribute ",
+ "with data ($data)\n",
+ "in phase $phase\n",
+ "in file $filename at line $linenum\n";
+ }
This creates a handler for the attribute C<:Loud> in the class LoudDecl.
Thereafter, any subroutine declared with a C<:Loud> attribute in the class
=item [5]
-the name of the phase in which the handler is being invoked.
+the name of the phase in which the handler is being invoked;
+
+=item [6]
+
+the filename in which the handler is being invoked;
+
+=item [7]
+
+the line number in this file.
=back
--- /dev/null
+#!perl
+
+BEGIN {
+ if ($ENV{PERL_CORE}) {
+ chdir 't' if -d 't';
+ @INC = '../lib';
+ }
+}
+
+use Test::More tests => 16;
+use Attribute::Handlers;
+
+sub Args : ATTR(CODE) {
+ my ($package, $symbol, $referent, $attr, $data, $phase, $filename, $linenum) = @_;
+ is( $package, 'main', 'package' );
+ is( $symbol, \*foo, 'symbol' );
+ is( $referent, \&foo, 'referent' );
+ is( $attr, 'Args', 'attr' );
+ is( $data, 'bar', 'data' );
+ is( $phase, 'CHECK', 'phase' );
+ is( $filename, __FILE__, 'filename' );
+ is( $linenum, 25, 'linenum' );
+}
+
+sub foo :Args(bar) {}
+
+my $bar :SArgs(grumpf);
+
+sub SArgs : ATTR(SCALAR) {
+ my ($package, $symbol, $referent, $attr, $data, $phase, $filename, $linenum) = @_;
+ is( $package, 'main', 'package' );
+ is( $symbol, 'LEXICAL', 'symbol' );
+ is( $referent, \$bar, 'referent' );
+ is( $attr, 'SArgs', 'attr' );
+ is( $data, 'grumpf', 'data' );
+ is( $phase, 'CHECK', 'phase' );
+ TODO: {
+ local $TODO = "Doesn't work correctly";
+ is( $filename, __FILE__, 'filename' );
+ is( $linenum, 25, 'linenum' );
+ }
+}