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