Commit | Line | Data |
dc4fc8c7 |
1 | package Package::DeprecationManager; |
2 | |
3 | use strict; |
4 | use warnings; |
5 | |
6 | use Carp qw( croak ); |
7 | use Params::Util qw( _HASH ); |
8 | use Sub::Install; |
9 | |
10 | sub import { |
11 | shift; |
12 | my %args = @_; |
13 | |
14 | croak |
15 | 'You must provide a hash reference -deprecations parameter when importing Package::DeprecationManager' |
16 | unless $args{-deprecations} && _HASH( $args{-deprecations} ); |
17 | |
18 | my %registry; |
19 | |
20 | my $import = _build_import( \%registry ); |
21 | my $warn = _build_warn( \%registry, $args{-deprecations} ); |
22 | |
23 | my $caller = caller(); |
24 | |
25 | Sub::Install::install_sub( |
26 | { |
27 | code => $import, |
28 | into => $caller, |
29 | as => 'import', |
30 | } |
31 | ); |
32 | |
33 | Sub::Install::install_sub( |
34 | { |
35 | code => $warn, |
36 | into => $caller, |
37 | as => 'deprecated', |
38 | } |
39 | ); |
40 | |
41 | return; |
42 | } |
43 | |
44 | sub _build_import { |
45 | my $registry = shift; |
46 | |
47 | return sub { |
48 | my $class = shift; |
49 | my %args = @_; |
50 | |
dee597ea |
51 | $args{-api_version} ||= delete $args{-compatible}; |
52 | |
dc4fc8c7 |
53 | $registry->{ caller() } = $args{-api_version} |
54 | if $args{-api_version}; |
55 | |
56 | return; |
57 | }; |
58 | } |
59 | |
60 | sub _build_warn { |
61 | my $registry = shift; |
62 | my $deprecated_at = shift; |
63 | |
64 | my %warned; |
65 | |
66 | return sub { |
67 | my ( $package, undef, undef, $sub ) = caller(1); |
68 | |
69 | my $compat_version = $registry->{$package}; |
70 | |
71 | my $deprecated_at = $deprecated_at->{$sub}; |
72 | |
73 | return |
74 | if defined $compat_version |
75 | && defined $deprecated_at |
76 | && $compat_version lt $deprecated_at; |
77 | |
78 | return if $warned{$package}{$sub}; |
79 | |
80 | if ( ! @_ ) { |
81 | my $msg = "$sub has been deprecated"; |
82 | $msg .= " since version $deprecated_at" |
83 | if defined $deprecated_at; |
84 | |
85 | @_ = $msg; |
86 | } |
87 | |
88 | $warned{$package}{$sub} = 1; |
89 | |
90 | goto &Carp::cluck; |
91 | }; |
92 | } |
93 | |
94 | 1; |
95 | |
96 | # ABSTRACT: Manage deprecation warnings for your distribution |
97 | |
98 | __END__ |
99 | |
100 | =pod |
101 | |
102 | =head1 SYNOPSIS |
103 | |
dee597ea |
104 | package My::Class; |
105 | |
106 | use Package::DeprecationManager |
107 | -deprecations => { |
108 | 'My::Class::foo' => '0.02', |
109 | 'My::Class::bar' => '0.05', |
110 | }; |
111 | |
112 | sub foo { |
113 | deprecated( 'Do not call foo!' ); |
114 | |
115 | ... |
116 | } |
117 | |
118 | sub bar { |
119 | deprecated(); |
120 | |
121 | ... |
122 | } |
123 | |
124 | package Other::Class; |
125 | |
126 | use My::Class -api_version => '0.04'; |
127 | |
128 | My::Class->new()->foo(); # warns |
129 | My::Class->new()->bar(); # does not warn |
130 | My::Class->new()->far(); # does not warn again |
dc4fc8c7 |
131 | |
132 | =head1 DESCRIPTION |
133 | |
dee597ea |
134 | This module allows you to manage a set of deprecations for one or more modules. |
135 | |
136 | When you import C<Package::DeprecationManager>, you must provide a set of |
137 | C<-deprecations> as a hash ref. The keys are fully qualified sub/method names, |
138 | and the values are the version when that subroutine was deprecated. |
139 | |
140 | As part of the import process, C<Package::DeprecationManager> will export two |
141 | subroutines into its caller. It proves an C<import()> sub for the caller and a |
142 | C<deprecated()> sub. |
143 | |
144 | The C<import()> sub allows callers of I<your> class to specify an C<-api_version> |
145 | parameter. If this is supplied, then deprecation warnings are only issued for |
146 | deprecations for api versions earlier than the one specified. |
147 | |
148 | You must call C<deprecated()> sub in each deprecated subroutine. When called, |
149 | it will issue a warning using C<Carp::cluck()>. If you do not pass an explicit |
150 | warning message, one will be generated for you. |
151 | |
152 | Deprecation warnings are only issued once for a given package, regardless of |
153 | how many times the deprecated sub/method is called. |
154 | |
dc4fc8c7 |
155 | =cut |