Escape any metacharacters in the anon prefix before using it in a regex
[gitmo/Moose.git] / lib / Class / MOP / Package.pm
1
2 package Class::MOP::Package;
3
4 use strict;
5 use warnings;
6
7 use Scalar::Util 'blessed', 'reftype', 'weaken';
8 use Carp         'confess';
9 use Devel::GlobalDestruction 'in_global_destruction';
10 use Package::Stash;
11
12 use base 'Class::MOP::Object';
13
14 # creation ...
15
16 sub initialize {
17     my ( $class, @args ) = @_;
18
19     unshift @args, "package" if @args % 2;
20
21     my %options = @args;
22     my $package_name = delete $options{package};
23
24
25     # we hand-construct the class 
26     # until we can bootstrap it
27     if ( my $meta = Class::MOP::get_metaclass_by_name($package_name) ) {
28         return $meta;
29     } else {
30         my $meta = ( ref $class || $class )->_new({
31             'package'   => $package_name,
32             %options,
33         });
34         Class::MOP::store_metaclass_by_name($package_name, $meta);
35
36         Class::MOP::weaken_metaclass($package_name) if $options{weaken};
37
38
39         return $meta;
40     }
41 }
42
43 sub reinitialize {
44     my ( $class, @args ) = @_;
45
46     unshift @args, "package" if @args % 2;
47
48     my %options = @args;
49     my $package_name = delete $options{package};
50
51     (defined $package_name && $package_name
52       && (!blessed $package_name || $package_name->isa('Class::MOP::Package')))
53         || confess "You must pass a package name or an existing Class::MOP::Package instance";
54
55     $package_name = $package_name->name
56         if blessed $package_name;
57
58     Class::MOP::remove_metaclass_by_name($package_name);
59
60     $class->initialize($package_name, %options); # call with first arg form for compat
61 }
62
63 sub create {
64     my $class = shift;
65     my @args = @_;
66
67     return $class->initialize(@args);
68 }
69
70 ## ANON packages
71
72 {
73     # NOTE:
74     # this should be sufficient, if you have a
75     # use case where it is not, write a test and
76     # I will change it.
77     my $ANON_SERIAL = 0;
78
79     my %ANON_PACKAGE_CACHE;
80
81     # NOTE:
82     # we need a sufficiently annoying prefix
83     # this should suffice for now, this is
84     # used in a couple of places below, so
85     # need to put it up here for now.
86     sub _anon_package_prefix { 'Class::MOP::Package::__ANON__::SERIAL::' }
87
88     sub is_anon {
89         my $self = shift;
90         no warnings 'uninitialized';
91         my $prefix = $self->_anon_package_prefix;
92         $self->name =~ /^\Q$prefix/;
93     }
94
95     sub create_anon {
96         my ($class, %options) = @_;
97
98         my $cache_ok = delete $options{cache};
99
100         my $cache_key;
101         if ($cache_ok) {
102             $cache_key = $class->_anon_cache_key(%options);
103
104             if (defined $ANON_PACKAGE_CACHE{$cache_key}) {
105                 return $ANON_PACKAGE_CACHE{$cache_key};
106             }
107         }
108
109         $options{weaken} = !$cache_ok unless exists $options{weaken};
110
111         my $package_name = $class->_anon_package_prefix . ++$ANON_SERIAL;
112
113         my $meta = $class->create($package_name, %options);
114
115         if ($cache_ok) {
116             $ANON_PACKAGE_CACHE{$cache_key} = $meta;
117             weaken($ANON_PACKAGE_CACHE{$cache_key});
118         }
119
120         return $meta;
121     }
122
123     sub _anon_cache_key { confess "Packages are not cacheable" }
124
125     sub DESTROY {
126         my $self = shift;
127
128         return if in_global_destruction(); # it'll happen soon anyway and this just makes things more complicated
129
130         $self->_free_anon
131             if $self->is_anon;
132     }
133
134     sub _free_anon {
135         my $self = shift;
136         my $name = $self->name;
137
138         # Moose does a weird thing where it replaces the metaclass for
139         # class when fixing metaclass incompatibility. In that case,
140         # we don't want to clean out the namespace now. We can detect
141         # that because Moose will explicitly update the singleton
142         # cache in Class::MOP.
143         no warnings 'uninitialized';
144         my $current_meta = Class::MOP::get_metaclass_by_name($name);
145         return if $current_meta ne $self;
146
147         my ($first_fragments, $last_fragment) = ($name =~ /^(.*)::(.*)$/);
148
149         no strict 'refs';
150         @{$name . '::ISA'} = ();
151         %{$name . '::'}    = ();
152         delete ${$first_fragments . '::'}{$last_fragment . '::'};
153
154         Class::MOP::remove_metaclass_by_name($name);
155     }
156
157 }
158
159 sub _new {
160     my $class = shift;
161
162     return Class::MOP::Class->initialize($class)->new_object(@_)
163         if $class ne __PACKAGE__;
164
165     my $params = @_ == 1 ? $_[0] : {@_};
166
167     return bless {
168         # Need to quote package to avoid a problem with PPI mis-parsing this
169         # as a package statement.
170         'package' => $params->{package},
171
172         # NOTE:
173         # because of issues with the Perl API
174         # to the typeglob in some versions, we
175         # need to just always grab a new
176         # reference to the hash in the accessor.
177         # Ideally we could just store a ref and
178         # it would Just Work, but oh well :\
179
180         namespace => \undef,
181
182     } => $class;
183 }
184
185 # Attributes
186
187 # NOTE:
188 # all these attribute readers will be bootstrapped 
189 # away in the Class::MOP bootstrap section
190
191 sub _package_stash {
192     $_[0]->{_package_stash} ||= Package::Stash->new($_[0]->name)
193 }
194 sub namespace {
195     $_[0]->_package_stash->namespace
196 }
197
198 # Class attributes
199
200 # ... these functions have to touch the symbol table itself,.. yuk
201
202 sub add_package_symbol {
203     my $self = shift;
204     $self->_package_stash->add_symbol(@_);
205 }
206
207 sub remove_package_glob {
208     my $self = shift;
209     $self->_package_stash->remove_glob(@_);
210 }
211
212 # ... these functions deal with stuff on the namespace level
213
214 sub has_package_symbol {
215     my $self = shift;
216     $self->_package_stash->has_symbol(@_);
217 }
218
219 sub get_package_symbol {
220     my $self = shift;
221     $self->_package_stash->get_symbol(@_);
222 }
223
224 sub get_or_add_package_symbol {
225     my $self = shift;
226     $self->_package_stash->get_or_add_symbol(@_);
227 }
228
229 sub remove_package_symbol {
230     my $self = shift;
231     $self->_package_stash->remove_symbol(@_);
232 }
233
234 sub list_all_package_symbols {
235     my $self = shift;
236     $self->_package_stash->list_all_symbols(@_);
237 }
238
239 sub get_all_package_symbols {
240     my $self = shift;
241     $self->_package_stash->get_all_symbols(@_);
242 }
243
244 1;
245
246 # ABSTRACT: Package Meta Object
247
248 __END__
249
250 =pod
251
252 =head1 DESCRIPTION
253
254 The Package Protocol provides an abstraction of a Perl 5 package. A
255 package is basically namespace, and this module provides methods for
256 looking at and changing that namespace's symbol table.
257
258 =head1 METHODS
259
260 =over 4
261
262 =item B<< Class::MOP::Package->initialize($package_name) >>
263
264 This method creates a new C<Class::MOP::Package> instance which
265 represents specified package. If an existing metaclass object exists
266 for the package, that will be returned instead.
267
268 =item B<< Class::MOP::Package->reinitialize($package) >>
269
270 This method forcibly removes any existing metaclass for the package
271 before calling C<initialize>. In contrast to C<initialize>, you may
272 also pass an existing C<Class::MOP::Package> instance instead of just
273 a package name as C<$package>.
274
275 Do not call this unless you know what you are doing.
276
277 =item B<< $metapackage->name >>
278
279 This is returns the package's name, as passed to the constructor.
280
281 =item B<< $metapackage->namespace >>
282
283 This returns a hash reference to the package's symbol table. The keys
284 are symbol names and the values are typeglob references.
285
286 =item B<< $metapackage->add_package_symbol($variable_name, $initial_value) >>
287
288 This method accepts a variable name and an optional initial value. The
289 C<$variable_name> must contain a leading sigil.
290
291 This method creates the variable in the package's symbol table, and
292 sets it to the initial value if one was provided.
293
294 =item B<< $metapackage->get_package_symbol($variable_name) >>
295
296 Given a variable name, this method returns the variable as a reference
297 or undef if it does not exist. The C<$variable_name> must contain a
298 leading sigil.
299
300 =item B<< $metapackage->get_or_add_package_symbol($variable_name) >>
301
302 Given a variable name, this method returns the variable as a reference.
303 If it does not exist, a default value will be generated if possible. The
304 C<$variable_name> must contain a leading sigil.
305
306 =item B<< $metapackage->has_package_symbol($variable_name) >>
307
308 Returns true if there is a package variable defined for
309 C<$variable_name>. The C<$variable_name> must contain a leading sigil.
310
311 =item B<< $metapackage->remove_package_symbol($variable_name) >>
312
313 This will remove the package variable specified C<$variable_name>. The
314 C<$variable_name> must contain a leading sigil.
315
316 =item B<< $metapackage->remove_package_glob($glob_name) >>
317
318 Given the name of a glob, this will remove that glob from the
319 package's symbol table. Glob names do not include a sigil. Removing
320 the glob removes all variables and subroutines with the specified
321 name.
322
323 =item B<< $metapackage->list_all_package_symbols($type_filter) >>
324
325 This will list all the glob names associated with the current
326 package. These names do not have leading sigils.
327
328 You can provide an optional type filter, which should be one of
329 'SCALAR', 'ARRAY', 'HASH', or 'CODE'.
330
331 =item B<< $metapackage->get_all_package_symbols($type_filter) >>
332
333 This works much like C<list_all_package_symbols>, but it returns a
334 hash reference. The keys are glob names and the values are references
335 to the value for that name.
336
337 =item B<< Class::MOP::Package->meta >>
338
339 This will return a L<Class::MOP::Class> instance for this class.
340
341 =back
342
343 =cut