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.2206';
3              
4 450     450   219953 use strict;
  450         1195  
  450         13039  
5 450     450   2471 use warnings;
  450         1092  
  450         12819  
6              
7 450     450   2477 use Scalar::Util 'blessed', 'weaken';
  450         1004  
  450         23914  
8 450     450   207121 use Devel::GlobalDestruction 'in_global_destruction';
  450         935540  
  450         2823  
9 450     450   37332 use Module::Runtime 'module_notional_filename';
  450         1304  
  450         2693  
10 450     450   18999 use Package::Stash;
  450         1038  
  450         9538  
11              
12 450     450   4559 use parent 'Class::MOP::Object';
  450         982  
  450         2564  
13              
14             # creation ...
15              
16             sub initialize {
17 2465     2465 1 41249 my ( $class, @args ) = @_;
18              
19 2465 50       11807 unshift @args, "package" if @args % 2;
20              
21 2465         10744 my %options = @args;
22 2465         18704 my $package_name = delete $options{package};
23              
24             # we hand-construct the class until we can bootstrap it
25 2465 100       8211 if ( my $meta = Class::MOP::get_metaclass_by_name($package_name) ) {
26 65         391 return $meta;
27             } else {
28 2400   66     54050 my $meta = ( ref $class || $class )->_new({
29             'package' => $package_name,
30             %options,
31             });
32 2400         11632 Class::MOP::store_metaclass_by_name($package_name, $meta);
33              
34 2400 100       15613 Class::MOP::weaken_metaclass($package_name) if $options{weaken};
35              
36              
37 2400         13780 return $meta;
38             }
39             }
40              
41             sub reinitialize {
42 135     135 1 1136 my ( $class, @args ) = @_;
43              
44 135 100       837 unshift @args, "package" if @args % 2;
45              
46 135         741 my %options = @args;
47 135         752 my $package_name = delete $options{package};
48              
49 135 100 100     2165 (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       795 $package_name = $package_name->name
56             if blessed $package_name;
57              
58 132         799 Class::MOP::remove_metaclass_by_name($package_name);
59              
60 132         1252 $class->initialize($package_name, %options); # call with first arg form for compat
61             }
62              
63             sub create {
64 1517     1517 1 5336 my $class = shift;
65 1517         4623 my @args = @_;
66              
67 1517         5900 my $meta = $class->initialize(@args);
68 1512         11158 my $filename = module_notional_filename($meta->name);
69             $INC{$filename} = '(set by Moose)'
70 1512 100       53511 unless exists $INC{$filename};
71              
72 1512         5705 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   15 sub _anon_package_prefix { 'Class::MOP::Package::__ANON__::SERIAL::' }
92              
93             sub is_anon {
94 265     265 1 2744 my $self = shift;
95 450     450   178524 no warnings 'uninitialized';
  450         1447  
  450         195357  
96 265         1061 my $prefix = $self->_anon_package_prefix;
97 265         6408 $self->name =~ /^\Q$prefix/;
98             }
99              
100             sub create_anon {
101 2838     2838 1 27915 my ($class, %options) = @_;
102              
103 2838         6803 my $cache_ok = delete $options{cache};
104 2838 100       10633 $options{weaken} = !$cache_ok unless exists $options{weaken};
105              
106 2838         4430 my $cache_key;
107 2838 100       6619 if ($cache_ok) {
108 2720         11563 $cache_key = $class->_anon_cache_key(%options);
109 2717 50       7983 undef $cache_ok if !defined($cache_key);
110             }
111              
112 2835 100       6491 if ($cache_ok) {
113 2717 100       9401 if (defined $ANON_PACKAGE_CACHE{$cache_key}) {
114 2156         16791 return $ANON_PACKAGE_CACHE{$cache_key};
115             }
116             }
117              
118 679         2677 my $package_name = $class->_anon_package_prefix . ++$ANON_SERIAL;
119              
120 679         3376 my $meta = $class->create($package_name, %options);
121              
122 675 100       2384 if ($cache_ok) {
123 561         2438 $ANON_PACKAGE_CACHE{$cache_key} = $meta;
124 561         2097 weaken($ANON_PACKAGE_CACHE{$cache_key});
125             }
126              
127 675         5027 return $meta;
128             }
129              
130             sub _anon_cache_key {
131 2     2   6 my $class = shift;
132 2         6 my %options = @_;
133 2         19 $class->_throw_exception( PackagesAndModulesAreNotCachable => class_name => $class,
134             params => \%options,
135             is_module => 0
136             );
137             }
138              
139             sub DESTROY {
140 315     315   41298 my $self = shift;
141              
142 315 50       7999 return if in_global_destruction(); # it'll happen soon anyway and this just makes things more complicated
143              
144 315 100       6588 $self->_free_anon
145             if $self->is_anon;
146             }
147              
148             sub _free_anon {
149 104     104   283 my $self = shift;
150 104         658 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 104         643 my $current_meta = Class::MOP::get_metaclass_by_name($name);
167 104 100 100     899 return if defined($current_meta) && $current_meta ne $self;
168              
169 97         659 my ($first_fragments, $last_fragment) = ($name =~ /^(.*)::(.*)$/);
170              
171 450     450   3934 no strict 'refs';
  450         1258  
  450         238304  
172             # clear @ISA first, to avoid a memory leak
173             # see https://rt.perl.org/rt3/Public/Bug/Display.html?id=92708
174 97         232 @{$name . '::ISA'} = ();
  97         2477  
175 97         448 %{$name . '::'} = ();
  97         1391  
176 97         273 delete ${$first_fragments . '::'}{$last_fragment . '::'};
  97         1164  
177              
178 97         943 Class::MOP::remove_metaclass_by_name($name);
179              
180 97         371 delete $INC{module_notional_filename($name)};
181             }
182              
183             }
184              
185             sub _new {
186 1074     1074   3036 my $class = shift;
187              
188 1074 100       4288 return Class::MOP::Class->initialize($class)->new_object(@_)
189             if $class ne __PACKAGE__;
190              
191 1073 50       4571 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         6681 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 516527   66 516527   4493312 $_[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 181365     181365 1 302314 my $self = shift;
230 181365         370165 $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 71317 my $self = shift;
242 43158         70071 $self->_package_stash->has_symbol(@_);
243             }
244              
245             sub get_package_symbol {
246 242776     242776 1 366142 my $self = shift;
247 242776         421362 $self->_package_stash->get_symbol(@_);
248             }
249              
250             sub get_or_add_package_symbol {
251 45439     45439 1 68189 my $self = shift;
252 45439         100568 $self->_package_stash->get_or_add_symbol(@_);
253             }
254              
255             sub remove_package_symbol {
256 345     345 1 2470 my $self = shift;
257 345         658 $self->_package_stash->remove_symbol(@_);
258             }
259              
260             sub list_all_package_symbols {
261 3445     3445 1 6533 my $self = shift;
262 3445         8725 $self->_package_stash->list_all_symbols(@_);
263             }
264              
265             sub get_all_package_symbols {
266 6     6 1 1148 my $self = shift;
267 6         17 $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.2206
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