File Coverage

blib/lib/Class/MOP/Package.pm
Criterion Covered Total %
statement 109 112 97.3
branch 32 36 88.8
condition 16 18 88.8
subroutine 27 29 93.1
pod 13 13 100.0
total 197 208 94.7


line stmt bran cond sub pod time code
1             package Class::MOP::Package;
2             our $VERSION = '2.2205';
3              
4 450     450   221308 use strict;
  450         1142  
  450         13023  
5 450     450   2388 use warnings;
  450         1039  
  450         12975  
6              
7 450     450   2515 use Scalar::Util 'blessed', 'weaken';
  450         1072  
  450         23920  
8 450     450   209352 use Devel::GlobalDestruction 'in_global_destruction';
  450         936214  
  450         2822  
9 450     450   36757 use Module::Runtime 'module_notional_filename';
  450         1282  
  450         2653  
10 450     450   19527 use Package::Stash;
  450         1030  
  450         9506  
11              
12 450     450   4606 use parent 'Class::MOP::Object';
  450         970  
  450         2514  
13              
14             # creation ...
15              
16             sub initialize {
17 2465     2465 1 40855 my ( $class, @args ) = @_;
18              
19 2465 50       11621 unshift @args, "package" if @args % 2;
20              
21 2465         10647 my %options = @args;
22 2465         18534 my $package_name = delete $options{package};
23              
24             # we hand-construct the class until we can bootstrap it
25 2465 100       8327 if ( my $meta = Class::MOP::get_metaclass_by_name($package_name) ) {
26 65         387 return $meta;
27             } else {
28 2400   66     54911 my $meta = ( ref $class || $class )->_new({
29             'package' => $package_name,
30             %options,
31             });
32 2400         11884 Class::MOP::store_metaclass_by_name($package_name, $meta);
33              
34 2400 100       15899 Class::MOP::weaken_metaclass($package_name) if $options{weaken};
35              
36              
37 2400         13760 return $meta;
38             }
39             }
40              
41             sub reinitialize {
42 135     135 1 1149 my ( $class, @args ) = @_;
43              
44 135 100       905 unshift @args, "package" if @args % 2;
45              
46 135         784 my %options = @args;
47 135         719 my $package_name = delete $options{package};
48              
49 135 100 100     2183 (defined $package_name && $package_name
      100        
      100        
50             && (!blessed $package_name || $package_name->isa('Class::MOP::Package')))
51             || $class->_throw_exception( MustPassAPackageNameOrAnExistingClassMOPPackageInstance => params => \%options,
52             class => $class
53             );
54              
55 132 100       792 $package_name = $package_name->name
56             if blessed $package_name;
57              
58 132         828 Class::MOP::remove_metaclass_by_name($package_name);
59              
60 132         1218 $class->initialize($package_name, %options); # call with first arg form for compat
61             }
62              
63             sub create {
64 1517     1517 1 5491 my $class = shift;
65 1517         4548 my @args = @_;
66              
67 1517         6131 my $meta = $class->initialize(@args);
68 1512         11190 my $filename = module_notional_filename($meta->name);
69             $INC{$filename} = '(set by Moose)'
70 1512 100       53498 unless exists $INC{$filename};
71              
72 1512         5838 return $meta;
73             }
74              
75             ## ANON packages
76              
77             {
78             # NOTE:
79             # this should be sufficient, if you have a
80             # use case where it is not, write a test and
81             # I will change it.
82             my $ANON_SERIAL = 0;
83              
84             my %ANON_PACKAGE_CACHE;
85              
86             # NOTE:
87             # we need a sufficiently annoying prefix
88             # this should suffice for now, this is
89             # used in a couple of places below, so
90             # need to put it up here for now.
91 5     5   14 sub _anon_package_prefix { 'Class::MOP::Package::__ANON__::SERIAL::' }
92              
93             sub is_anon {
94 265     265 1 2569 my $self = shift;
95 450     450   178616 no warnings 'uninitialized';
  450         1472  
  450         197480  
96 265         1107 my $prefix = $self->_anon_package_prefix;
97 265         6242 $self->name =~ /^\Q$prefix/;
98             }
99              
100             sub create_anon {
101 2838     2838 1 30260 my ($class, %options) = @_;
102              
103 2838         6636 my $cache_ok = delete $options{cache};
104 2838 100       10884 $options{weaken} = !$cache_ok unless exists $options{weaken};
105              
106 2838         4395 my $cache_key;
107 2838 100       6834 if ($cache_ok) {
108 2720         11761 $cache_key = $class->_anon_cache_key(%options);
109 2717 50       7751 undef $cache_ok if !defined($cache_key);
110             }
111              
112 2835 100       6575 if ($cache_ok) {
113 2717 100       9309 if (defined $ANON_PACKAGE_CACHE{$cache_key}) {
114 2156         16812 return $ANON_PACKAGE_CACHE{$cache_key};
115             }
116             }
117              
118 679         2732 my $package_name = $class->_anon_package_prefix . ++$ANON_SERIAL;
119              
120 679         3391 my $meta = $class->create($package_name, %options);
121              
122 675 100       2486 if ($cache_ok) {
123 561         2477 $ANON_PACKAGE_CACHE{$cache_key} = $meta;
124 561         2088 weaken($ANON_PACKAGE_CACHE{$cache_key});
125             }
126              
127 675         5076 return $meta;
128             }
129              
130             sub _anon_cache_key {
131 2     2   5 my $class = shift;
132 2         6 my %options = @_;
133 2         13 $class->_throw_exception( PackagesAndModulesAreNotCachable => class_name => $class,
134             params => \%options,
135             is_module => 0
136             );
137             }
138              
139             sub DESTROY {
140 315     315   40608 my $self = shift;
141              
142 315 50       8905 return if in_global_destruction(); # it'll happen soon anyway and this just makes things more complicated
143              
144 315 100       6717 $self->_free_anon
145             if $self->is_anon;
146             }
147              
148             sub _free_anon {
149 103     103   322 my $self = shift;
150 103         733 my $name = $self->name;
151              
152             # Moose does a weird thing where it replaces the metaclass for
153             # class when fixing metaclass incompatibility. In that case,
154             # we don't want to clean out the namespace now. We can detect
155             # that because Moose will explicitly update the singleton
156             # cache in Class::MOP using store_metaclass_by_name, which
157             # means that the new metaclass will already exist in the cache
158             # by this point.
159             # The other options here are that $current_meta can be undef if
160             # remove_metaclass_by_name is called explicitly (since the hash
161             # entry is removed first, and then this destructor is called),
162             # or that $current_meta can be the same as $self, which happens
163             # when the metaclass goes out of scope (since the weak reference
164             # in the metaclass cache won't be freed until after this
165             # destructor runs).
166 103         425 my $current_meta = Class::MOP::get_metaclass_by_name($name);
167 103 100 100     985 return if defined($current_meta) && $current_meta ne $self;
168              
169 96         744 my ($first_fragments, $last_fragment) = ($name =~ /^(.*)::(.*)$/);
170              
171 450     450   3968 no strict 'refs';
  450         1233  
  450         237670  
172             # clear @ISA first, to avoid a memory leak
173             # see https://rt.perl.org/rt3/Public/Bug/Display.html?id=92708
174 96         256 @{$name . '::ISA'} = ();
  96         2784  
175 96         627 %{$name . '::'} = ();
  96         1591  
176 96         296 delete ${$first_fragments . '::'}{$last_fragment . '::'};
  96         1159  
177              
178 96         1014 Class::MOP::remove_metaclass_by_name($name);
179              
180 96         494 delete $INC{module_notional_filename($name)};
181             }
182              
183             }
184              
185             sub _new {
186 1074     1074   3088 my $class = shift;
187              
188 1074 100       4197 return Class::MOP::Class->initialize($class)->new_object(@_)
189             if $class ne __PACKAGE__;
190              
191 1073 50       4649 my $params = @_ == 1 ? $_[0] : {@_};
192              
193             return bless {
194             # Need to quote package to avoid a problem with PPI mis-parsing this
195             # as a package statement.
196             'package' => $params->{package},
197              
198             # NOTE:
199             # because of issues with the Perl API
200             # to the typeglob in some versions, we
201             # need to just always grab a new
202             # reference to the hash in the accessor.
203             # Ideally we could just store a ref and
204             # it would Just Work, but oh well :\
205              
206 1073         6656 namespace => \undef,
207              
208             } => $class;
209             }
210              
211             # Attributes
212              
213             # NOTE:
214             # all these attribute readers will be bootstrapped
215             # away in the Class::MOP bootstrap section
216              
217             sub _package_stash {
218 516528   66 516528   4501151 $_[0]->{_package_stash} ||= Package::Stash->new($_[0]->name)
219             }
220             sub namespace {
221 0     0   0 $_[0]->_package_stash->namespace
222             }
223              
224             # Class attributes
225              
226             # ... these functions have to touch the symbol table itself,.. yuk
227              
228             sub add_package_symbol {
229 181367     181367 1 303543 my $self = shift;
230 181367         369547 $self->_package_stash->add_symbol(@_);
231             }
232              
233             sub remove_package_glob {
234 0     0 1 0 my $self = shift;
235 0         0 $self->_package_stash->remove_glob(@_);
236             }
237              
238             # ... these functions deal with stuff on the namespace level
239              
240             sub has_package_symbol {
241 43158     43158 1 70643 my $self = shift;
242 43158         70219 $self->_package_stash->has_symbol(@_);
243             }
244              
245             sub get_package_symbol {
246 242775     242775 1 369708 my $self = shift;
247 242775         422832 $self->_package_stash->get_symbol(@_);
248             }
249              
250             sub get_or_add_package_symbol {
251 45439     45439 1 69341 my $self = shift;
252 45439         100601 $self->_package_stash->get_or_add_symbol(@_);
253             }
254              
255             sub remove_package_symbol {
256 345     345 1 2335 my $self = shift;
257 345         649 $self->_package_stash->remove_symbol(@_);
258             }
259              
260             sub list_all_package_symbols {
261 3445     3445 1 6539 my $self = shift;
262 3445         8920 $self->_package_stash->list_all_symbols(@_);
263             }
264              
265             sub get_all_package_symbols {
266 6     6 1 1206 my $self = shift;
267 6         18 $self->_package_stash->get_all_symbols(@_);
268             }
269              
270             1;
271              
272             # ABSTRACT: Package Meta Object
273              
274             __END__
275              
276             =pod
277              
278             =encoding UTF-8
279              
280             =head1 NAME
281              
282             Class::MOP::Package - Package Meta Object
283              
284             =head1 VERSION
285              
286             version 2.2205
287              
288             =head1 DESCRIPTION
289              
290             The Package Protocol provides an abstraction of a Perl 5 package. A
291             package is basically namespace, and this module provides methods for
292             looking at and changing that namespace's symbol table.
293              
294             =head1 METHODS
295              
296             =head2 Class::MOP::Package->initialize($package_name, %options)
297              
298             This method creates a new C<Class::MOP::Package> instance which
299             represents specified package. If an existing metaclass object exists
300             for the package, that will be returned instead. No options are valid at the
301             package level.
302              
303             =head2 Class::MOP::Package->reinitialize($package, %options)
304              
305             This method forcibly removes any existing metaclass for the package
306             before calling C<initialize>. In contrast to C<initialize>, you may
307             also pass an existing C<Class::MOP::Package> instance instead of just
308             a package name as C<$package>.
309              
310             Do not call this unless you know what you are doing.
311              
312             =head2 Class::MOP::Package->create($package, %options)
313              
314             Creates a new C<Class::MOP::Package> instance which represents the specified
315             package, and also does some initialization of that package. Currently, this
316             just does the same thing as C<initialize>, but is overridden in subclasses,
317             such as C<Class::MOP::Class>.
318              
319             =head2 Class::MOP::Package->create_anon(%options)
320              
321             Creates a new anonymous package. Valid keys for C<%options> are:
322              
323             =over 4
324              
325             =item C<cache>
326              
327             If this will be C<true> (the default is C<false>), the instance will be cached
328             in C<Class::MOP>'s metaclass cache.
329              
330             =item C<weaken>
331              
332             If this is C<true> (the default C<true> when L<cache> is C<false>), the instance
333             stored in C<Class::MOP>'s metaclass cache will be weakened, so that the
334             anonymous package will be garbage collected when the returned instance goes out
335             of scope.
336              
337             =back
338              
339             =head2 $metapackage->is_anon
340              
341             Returns true if the package is an anonymous package.
342              
343             =head2 $metapackage->name
344              
345             This is returns the package's name, as passed to the constructor.
346              
347             =head2 $metapackage->namespace
348              
349             This returns a hash reference to the package's symbol table. The keys
350             are symbol names and the values are typeglob references.
351              
352             =head2 $metapackage->add_package_symbol($variable_name, $initial_value)
353              
354             This method accepts a variable name and an optional initial value. The
355             C<$variable_name> must contain a leading sigil.
356              
357             This method creates the variable in the package's symbol table, and
358             sets it to the initial value if one was provided.
359              
360             =head2 $metapackage->get_package_symbol($variable_name)
361              
362             Given a variable name, this method returns the variable as a reference
363             or undef if it does not exist. The C<$variable_name> must contain a
364             leading sigil.
365              
366             =head2 $metapackage->get_or_add_package_symbol($variable_name)
367              
368             Given a variable name, this method returns the variable as a reference.
369             If it does not exist, a default value will be generated if possible. The
370             C<$variable_name> must contain a leading sigil.
371              
372             =head2 $metapackage->has_package_symbol($variable_name)
373              
374             Returns true if there is a package variable defined for
375             C<$variable_name>. The C<$variable_name> must contain a leading sigil.
376              
377             =head2 $metapackage->remove_package_symbol($variable_name)
378              
379             This will remove the package variable specified C<$variable_name>. The
380             C<$variable_name> must contain a leading sigil.
381              
382             =head2 $metapackage->remove_package_glob($glob_name)
383              
384             Given the name of a glob, this will remove that glob from the
385             package's symbol table. Glob names do not include a sigil. Removing
386             the glob removes all variables and subroutines with the specified
387             name.
388              
389             =head2 $metapackage->list_all_package_symbols($type_filter)
390              
391             This will list all the glob names associated with the current
392             package. These names do not have leading sigils.
393              
394             You can provide an optional type filter, which should be one of
395             'SCALAR', 'ARRAY', 'HASH', or 'CODE'.
396              
397             =head2 $metapackage->get_all_package_symbols($type_filter)
398              
399             This works much like C<list_all_package_symbols>, but it returns a
400             hash reference. The keys are glob names and the values are references
401             to the value for that name.
402              
403             =head2 Class::MOP::Package->meta
404              
405             This will return a L<Class::MOP::Class> instance for this class.
406              
407             =head1 AUTHORS
408              
409             =over 4
410              
411             =item *
412              
413             Stevan Little <stevan@cpan.org>
414              
415             =item *
416              
417             Dave Rolsky <autarch@urth.org>
418              
419             =item *
420              
421             Jesse Luehrs <doy@cpan.org>
422              
423             =item *
424              
425             Shawn M Moore <sartak@cpan.org>
426              
427             =item *
428              
429             יובל קוג'מן (Yuval Kogman) <nothingmuch@woobling.org>
430              
431             =item *
432              
433             Karen Etheridge <ether@cpan.org>
434              
435             =item *
436              
437             Florian Ragwitz <rafl@debian.org>
438              
439             =item *
440              
441             Hans Dieter Pearcey <hdp@cpan.org>
442              
443             =item *
444              
445             Chris Prather <chris@prather.org>
446              
447             =item *
448              
449             Matt S Trout <mstrout@cpan.org>
450              
451             =back
452              
453             =head1 COPYRIGHT AND LICENSE
454              
455             This software is copyright (c) 2006 by Infinity Interactive, Inc.
456              
457             This is free software; you can redistribute it and/or modify it under
458             the same terms as the Perl 5 programming language system itself.
459              
460             =cut