Fix incorrect warning/exception originator
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Carp.pm
CommitLineData
9851271f 1package # hide from pause
2 DBIx::Class::Carp;
70c28808 3
4use strict;
5use warnings;
6
e0b2dc74 7# This is here instead of DBIx::Class because of load-order issues
8BEGIN {
cd122820 9 # something is tripping up V::M on 5.8.1, leading to segfaults.
10 # A similar test in n::c itself is disabled on 5.8.1 for the same
11 # reason. There isn't much motivation to try to find why it happens
e0b2dc74 12 *DBIx::Class::_ENV_::BROKEN_NAMESPACE_CLEAN = ($] < 5.008005)
13 ? sub () { 1 }
14 : sub () { 0 }
15 ;
16}
17
70c28808 18use Carp ();
19use namespace::clean ();
20
5e0e5426 21$Carp::Internal{ (__PACKAGE__) }++;
22
70c28808 23sub __find_caller {
24 my ($skip_pattern, $class) = @_;
25
26 my $skip_class_data = $class->_skip_namespace_frames
27 if ($class and $class->can('_skip_namespace_frames'));
28
29 $skip_pattern = qr/$skip_pattern|$skip_class_data/
30 if $skip_class_data;
31
32 my $fr_num = 1; # skip us and the calling carp*
5e0e5426 33
34 my (@f, $origin);
70c28808 35 while (@f = caller($fr_num++)) {
5e0e5426 36
37 next if
38 ( $f[3] eq '(eval)' or $f[3] =~ /::__ANON__$/ );
39
40 $origin ||= (
41 $f[3] =~ /^ (.+) :: ([^\:]+) $/x
42 and
43 ! $Carp::Internal{$1}
44 and
45 $2 !~ /^(?: throw_exception | carp | carp_unique | carp_once )$/x
46 ) ? $f[3] : undef;
47
cd122820 48 if (
49 $f[0]->can('_skip_namespace_frames')
50 and
51 my $extra_skip = $f[0]->_skip_namespace_frames
52 ) {
53 $skip_pattern = qr/$skip_pattern|$extra_skip/;
54 }
81fecf64 55
56 last if $f[0] !~ $skip_pattern;
70c28808 57 }
58
5e0e5426 59 my $site = @f # if empty - nothing matched - full stack
60 ? "at $f[1] line $f[2]"
61 : Carp::longmess()
70c28808 62 ;
5e0e5426 63 $origin ||= '{UNKNOWN}';
70c28808 64
65 return (
5e0e5426 66 $site,
67 $origin =~ /::/ ? "$origin(): " : "$origin: ", # cargo-cult from Carp::Clan
70c28808 68 );
69};
70
71my $warn = sub {
72 my ($ln, @warn) = @_;
73 @warn = "Warning: something's wrong" unless @warn;
74
75 # back-compat with Carp::Clan - a warning ending with \n does
76 # not include caller info
77 warn (
78 @warn,
79 $warn[-1] =~ /\n$/ ? '' : " $ln\n"
80 );
81};
82
83sub import {
84 my (undef, $skip_pattern) = @_;
85 my $into = caller;
86
87 $skip_pattern = $skip_pattern
569b96bb 88 ? qr/ ^ $into $ | $skip_pattern /x
89 : qr/ ^ $into $ /x
70c28808 90 ;
91
92 no strict 'refs';
93
94 *{"${into}::carp"} = sub {
95 $warn->(
96 __find_caller($skip_pattern, $into),
97 @_
98 );
99 };
100
8fda97d5 101 my $fired = {};
70c28808 102 *{"${into}::carp_once"} = sub {
8fda97d5 103 return if $fired->{$_[0]};
104 $fired->{$_[0]} = 1;
70c28808 105
106 $warn->(
107 __find_caller($skip_pattern, $into),
108 @_,
109 );
110 };
111
112 my $seen;
113 *{"${into}::carp_unique"} = sub {
114 my ($ln, $calling) = __find_caller($skip_pattern, $into);
115 my $msg = join ('', $calling, @_);
116
117 # unique carping with a hidden caller makes no sense
118 $msg =~ s/\n+$//;
119
120 return if $seen->{$ln}{$msg};
121 $seen->{$ln}{$msg} = 1;
122
123 $warn->(
124 $ln,
125 $msg,
126 );
127 };
128
129 # cleanup after ourselves
90cfe42b 130 namespace::clean->import(-cleanee => $into, qw/carp carp_once carp_unique/)
131 ## FIXME FIXME FIXME - something is tripping up V::M on 5.8.1, leading
132 # to segfaults. When n::c/B::H::EndOfScope is rewritten in terms of tie()
133 # see if this starts working
0d8817bc 134 unless DBIx::Class::_ENV_::BROKEN_NAMESPACE_CLEAN;
70c28808 135}
136
137sub unimport {
138 die (__PACKAGE__ . " does not implement unimport yet\n");
139}
140
1411;
142
143=head1 NAME
144
145DBIx::Class::Carp - Provides advanced Carp::Clan-like warning functions for DBIx::Class internals
146
147=head1 DESCRIPTION
148
149Documentation is lacking on purpose - this an experiment not yet fit for
150mass consumption. If you use this do not count on any kind of stability,
151in fact don't even count on this module's continuing existence (it has
152been noindexed for a reason).
153
154In addition to the classic interface:
155
156 use DBIx::Class::Carp '^DBIx::Class'
157
158this module also supports a class-data based way to specify the exclusion
159regex. A message is only carped from a callsite that matches neither the
160closed over string, nor the value of L</_skip_namespace_frames> as declared
cd122820 161on any callframe already skipped due to the same mechanism. This is to ensure
162that intermediate callsites can declare their own additional skip-namespaces.
70c28808 163
164=head1 CLASS ATTRIBUTES
165
166=head2 _skip_namespace_frames
167
168A classdata attribute holding the stringified regex matching callsites that
169should be skipped by the carp methods below. An empty string C<q{}> is treated
170like no setting/C<undef> (the distinction is necessary due to semantics of the
171class data accessors provided by L<Class::Accessor::Grouped>)
172
173=head1 EXPORTED FUNCTIONS
174
175This module export the following 3 functions. Only warning related C<carp*>
176is being handled here, for C<croak>-ing you must use
177L<DBIx::Class::Schema/throw_exception> or L<DBIx::Class::Exception>.
178
179=head2 carp
180
181Carps message with the file/line of the first callsite not matching
182L</_skip_namespace_frames> nor the closed-over arguments to
183C<use DBIx::Class::Carp>.
184
185=head2 carp_unique
186
187Like L</carp> but warns once for every distinct callsite (subject to the
188same ruleset as L</carp>).
189
190=head2 carp_once
191
192Like L</carp> but warns only once for the life of the perl interpreter
193(regardless of callsite).
194
195=cut