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.2203';
3              
4 462     462   193036 use strict;
  462         938  
  462         11791  
5 462     462   2001 use warnings;
  462         826  
  462         10962  
6              
7 462     462   2070 use Scalar::Util 'blessed', 'weaken';
  462         853  
  462         20842  
8 462     462   175199 use Devel::GlobalDestruction 'in_global_destruction';
  462         821082  
  462         2453  
9 462     462   32209 use Module::Runtime 'module_notional_filename';
  462         1092  
  462         2296  
10 462     462   16812 use Package::Stash;
  462         941  
  462         8585  
11              
12 462     462   4129 use parent 'Class::MOP::Object';
  462         835  
  462         2118  
13              
14             # creation ...
15              
16             sub initialize {
17 2518     2518 1 40874 my ( $class, @args ) = @_;
18              
19 2518 50       10445 unshift @args, "package" if @args % 2;
20              
21 2518         9838 my %options = @args;
22 2518         16583 my $package_name = delete $options{package};
23              
24             # we hand-construct the class until we can bootstrap it
25 2518 100       7450 if ( my $meta = Class::MOP::get_metaclass_by_name($package_name) ) {
26 65         256 return $meta;
27             } else {
28 2453   66     47639 my $meta = ( ref $class || $class )->_new({
29             'package' => $package_name,
30             %options,
31             });
32 2453         10497 Class::MOP::store_metaclass_by_name($package_name, $meta);
33              
34 2453 100       13976 Class::MOP::weaken_metaclass($package_name) if $options{weaken};
35              
36              
37 2453         12354 return $meta;
38             }
39             }
40              
41             sub reinitialize {
42 136     136 1 899 my ( $class, @args ) = @_;
43              
44 136 100       868 unshift @args, "package" if @args % 2;
45              
46 136         631 my %options = @args;
47 136         641 my $package_name = delete $options{package};
48              
49 136 100 100     1965 (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 133 100       669 $package_name = $package_name->name
56             if blessed $package_name;
57              
58 133         787 Class::MOP::remove_metaclass_by_name($package_name);
59              
60 133         1117 $class->initialize($package_name, %options); # call with first arg form for compat
61             }
62              
63             sub create {
64 1540     1540 1 6279 my $class = shift;
65 1540         4903 my @args = @_;
66              
67 1540         5296 my $meta = $class->initialize(@args);
68 1535         12001 my $filename = module_notional_filename($meta->name);
69             $INC{$filename} = '(set by Moose)'
70 1535 100       47272 unless exists $INC{$filename};
71              
72 1535         5993 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   12 sub _anon_package_prefix { 'Class::MOP::Package::__ANON__::SERIAL::' }
92              
93             sub is_anon {
94 264     264 1 1844 my $self = shift;
95 462     462   161550 no warnings 'uninitialized';
  462         1202  
  462         175051  
96 264         893 my $prefix = $self->_anon_package_prefix;
97 264         5438 $self->name =~ /^\Q$prefix/;
98             }
99              
100             sub create_anon {
101 2843     2843 1 24243 my ($class, %options) = @_;
102              
103 2843         5607 my $cache_ok = delete $options{cache};
104 2843 100       9322 $options{weaken} = !$cache_ok unless exists $options{weaken};
105              
106 2843         3953 my $cache_key;
107 2843 100       5632 if ($cache_ok) {
108 2724         10236 $cache_key = $class->_anon_cache_key(%options);
109 2721 50       6798 undef $cache_ok if !defined($cache_key);
110             }
111              
112 2840 100       5670 if ($cache_ok) {
113 2721 100       7665 if (defined $ANON_PACKAGE_CACHE{$cache_key}) {
114 2156         13809 return $ANON_PACKAGE_CACHE{$cache_key};
115             }
116             }
117              
118 684         2359 my $package_name = $class->_anon_package_prefix . ++$ANON_SERIAL;
119              
120 684         3030 my $meta = $class->create($package_name, %options);
121              
122 680 100       2158 if ($cache_ok) {
123 565         2145 $ANON_PACKAGE_CACHE{$cache_key} = $meta;
124 565         1823 weaken($ANON_PACKAGE_CACHE{$cache_key});
125             }
126              
127 680         4653 return $meta;
128             }
129              
130             sub _anon_cache_key {
131 2     2   6 my $class = shift;
132 2         5 my %options = @_;
133 2         14 $class->_throw_exception( PackagesAndModulesAreNotCachable => class_name => $class,
134             params => \%options,
135             is_module => 0
136             );
137             }
138              
139             sub DESTROY {
140 312     312   37614 my $self = shift;
141              
142 312 50       6956 return if in_global_destruction(); # it'll happen soon anyway and this just makes things more complicated
143              
144 312 100       5292 $self->_free_anon
145             if $self->is_anon;
146             }
147              
148             sub _free_anon {
149 102     102   265 my $self = shift;
150 102         490 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 102         446 my $current_meta = Class::MOP::get_metaclass_by_name($name);
167 102 100 100     741 return if defined($current_meta) && $current_meta ne $self;
168              
169 96         606 my ($first_fragments, $last_fragment) = ($name =~ /^(.*)::(.*)$/);
170              
171 462     462   3614 no strict 'refs';
  462         1184  
  462         214039  
172             # clear @ISA first, to avoid a memory leak
173             # see https://rt.perl.org/rt3/Public/Bug/Display.html?id=92708
174 96         185 @{$name . '::ISA'} = ();
  96         2208  
175 96         424 %{$name . '::'} = ();
  96         1262  
176 96         225 delete ${$first_fragments . '::'}{$last_fragment . '::'};
  96         886  
177              
178 96         782 Class::MOP::remove_metaclass_by_name($name);
179              
180 96         366 delete $INC{module_notional_filename($name)};
181             }
182              
183             }
184              
185             sub _new {
186 1121     1121   2693 my $class = shift;
187              
188 1121 100       3897 return Class::MOP::Class->initialize($class)->new_object(@_)
189             if $class ne __PACKAGE__;
190              
191 1120 50       4133 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 1120         6347 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 528540   66 528540   3957383 $_[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 185924     185924 1 276160 my $self = shift;
230 185924         336791 $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 43921     43921 1 62405 my $self = shift;
242 43921         63158 $self->_package_stash->has_symbol(@_);
243             }
244              
245             sub get_package_symbol {
246 248247     248247 1 328512 my $self = shift;
247 248247         377754 $self->_package_stash->get_symbol(@_);
248             }
249              
250             sub get_or_add_package_symbol {
251 46598     46598 1 62826 my $self = shift;
252 46598         90071 $self->_package_stash->get_or_add_symbol(@_);
253             }
254              
255             sub remove_package_symbol {
256 347     347 1 2401 my $self = shift;
257 347         606 $self->_package_stash->remove_symbol(@_);
258             }
259              
260             sub list_all_package_symbols {
261 3504     3504 1 5718 my $self = shift;
262 3504         7838 $self->_package_stash->list_all_symbols(@_);
263             }
264              
265             sub get_all_package_symbols {
266 6     6 1 1334 my $self = shift;
267 6         15 $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.2203
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