1 package Class::Inspector;
7 Class::Inspector - Get information about a class and its structure
13 # Is a class installed and/or loaded
14 Class::Inspector->installed( 'Foo::Class' );
15 Class::Inspector->loaded( 'Foo::Class' );
17 # Filename related information
18 Class::Inspector->filename( 'Foo::Class' );
19 Class::Inspector->resolved_filename( 'Foo::Class' );
21 # Get subroutine related information
22 Class::Inspector->functions( 'Foo::Class' );
23 Class::Inspector->function_refs( 'Foo::Class' );
24 Class::Inspector->function_exists( 'Foo::Class', 'bar' );
25 Class::Inspector->methods( 'Foo::Class', 'full', 'public' );
27 # Find all loaded subclasses or something
28 Class::Inspector->subclasses( 'Foo::Class' );
32 Class::Inspector allows you to get information about a loaded class. Most or
33 all of this information can be found in other ways, but they aren't always
34 very friendly, and usually involve a relatively high level of Perl wizardry,
35 or strange and unusual looking code. Class::Inspector attempts to provide
36 an easier, more friendly interface to this information.
43 # We don't want to use strict refs anywhere in this module, since we do a
44 # lot of things in here that aren't strict refs friendly.
45 use strict qw{vars subs};
50 use vars qw{$VERSION $RE_IDENTIFIER $RE_CLASS $UNIX};
54 # If Unicode is available, enable it so that the
55 # pattern matches below match unicode method names.
56 # We can safely ignore any failure here.
58 eval "require utf8; utf8->import";
60 # Predefine some regexs
61 $RE_IDENTIFIER = qr/\A[^\W\d]\w*\z/s;
62 $RE_CLASS = qr/\A[^\W\d]\w*(?:(?:\'|::)\w+)*\z/s;
64 # Are we on something Unix-like?
65 $UNIX = !! ( $File::Spec::ISA[0] eq 'File::Spec::Unix' );
72 #####################################################################
77 =head2 installed $class
79 The C<installed> static method tries to determine if a class is installed
80 on the machine, or at least available to Perl. It does this by wrapping
81 around C<resolved_filename>.
83 Returns true if installed/available, false if the class is not installed,
84 or C<undef> if the class name is invalid.
90 !! ($class->loaded_filename($_[0]) or $class->resolved_filename($_[0]));
97 The C<loaded> static method tries to determine if a class is loaded by
98 looking for symbol table entries.
100 This method it uses to determine this will work even if the class does not
101 have its own file, but is contained inside a single file with multiple
102 classes in it. Even in the case of some sort of run-time loading class
103 being used, these typically leave some trace in the symbol table, so an
104 L<Autoload> or L<Class::Autouse>-based class should correctly appear
107 Returns true if the class is loaded, false if not, or C<undef> if the
108 class name is invalid.
114 my $name = $class->_class(shift) or return undef;
115 $class->_loaded($name);
119 my ($class, $name) = @_;
121 # Handle by far the two most common cases
122 # This is very fast and handles 99% of cases.
123 return 1 if defined ${"${name}::VERSION"};
124 return 1 if defined @{"${name}::ISA"};
126 # Are there any symbol table entries other than other namespaces
127 foreach ( keys %{"${name}::"} ) {
128 next if substr($_, -2, 2) eq '::';
129 return 1 if defined &{"${name}::$_"};
132 # No functions, and it doesn't have a version, and isn't anything.
133 # As an absolute last resort, check for an entry in %INC
134 my $filename = $class->_inc_filename($name);
135 return 1 if defined $INC{$filename};
142 =head2 filename $class
144 For a given class, returns the base filename for the class. This will NOT
145 be a fully resolved filename, just the part of the filename BELOW the
148 print Class->filename( 'Foo::Bar' );
151 This filename will be returned with the right seperator for the local
152 platform, and should work on all platforms.
154 Returns the filename on success or C<undef> if the class name is invalid.
160 my $name = $class->_class(shift) or return undef;
161 File::Spec->catfile( split /(?:\'|::)/, $name ) . '.pm';
166 =head2 resolved_filename $class, @try_first
168 For a given class, the C<resolved_filename> static method returns the fully
169 resolved filename for a class. That is, the file that the class would be
172 This is not nescesarily the file that the class WAS loaded from, as the
173 value returned is determined each time it runs, and the C<@INC> include
176 To get the actual file for a loaded class, see the C<loaded_filename>
179 Returns the filename for the class, or C<undef> if the class name is
184 sub resolved_filename {
186 my $filename = $class->_inc_filename(shift) or return undef;
189 # Look through the @INC path to find the file
190 foreach ( @try_first, @INC ) {
191 my $full = "$_/$filename";
192 next unless -e $full;
193 return $UNIX ? $full : $class->_inc_to_local($full);
202 =head2 loaded_filename $class
204 For a given loaded class, the C<loaded_filename> static method determines
205 (via the C<%INC> hash) the name of the file that it was originally loaded
208 Returns a resolved file path, or false if the class did not have it's own
213 sub loaded_filename {
215 my $filename = $class->_inc_filename(shift);
216 $UNIX ? $INC{$filename} : $class->_inc_to_local($INC{$filename});
223 #####################################################################
224 # Sub Related Methods
228 =head2 functions $class
230 For a loaded class, the C<functions> static method returns a list of the
231 names of all the functions in the classes immediate namespace.
233 Note that this is not the METHODS of the class, just the functions.
235 Returns a reference to an array of the function names on success, or C<undef>
236 if the class name is invalid or the class is not loaded.
242 my $name = $class->_class(shift) or return undef;
243 return undef unless $class->loaded( $name );
245 # Get all the CODE symbol table entries
246 my @functions = sort grep { /$RE_IDENTIFIER/o }
247 grep { defined &{"${name}::$_"} }
254 =head2 function_refs $class
256 For a loaded class, the C<function_refs> static method returns references to
257 all the functions in the classes immediate namespace.
259 Note that this is not the METHODS of the class, just the functions.
261 Returns a reference to an array of C<CODE> refs of the functions on
262 success, or C<undef> if the class is not loaded.
268 my $name = $class->_class(shift) or return undef;
269 return undef unless $class->loaded( $name );
271 # Get all the CODE symbol table entries, but return
272 # the actual CODE refs this time.
273 my @functions = map { \&{"${name}::$_"} }
274 sort grep { /$RE_IDENTIFIER/o }
275 grep { defined &{"${name}::$_"} }
282 =head2 function_exists $class, $function
284 Given a class and function name the C<function_exists> static method will
285 check to see if the function exists in the class.
287 Note that this is as a function, not as a method. To see if a method
288 exists for a class, use the C<can> method for any class or object.
290 Returns true if the function exists, false if not, or C<undef> if the
291 class or function name are invalid, or the class is not loaded.
295 sub function_exists {
297 my $name = $class->_class( shift ) or return undef;
298 my $function = shift or return undef;
300 # Only works if the class is loaded
301 return undef unless $class->loaded( $name );
303 # Does the GLOB exist and its CODE part exist
304 defined &{"${name}::$function"};
309 =head2 methods $class, @options
311 For a given class name, the C<methods> static method will returns ALL
312 the methods available to that class. This includes all methods available
313 from every class up the class' C<@ISA> tree.
315 Returns a reference to an array of the names of all the available methods
316 on success, or C<undef> if the class name is invalid or the class is not
319 A number of options are available to the C<methods> method that will alter
320 the results returned. These should be listed after the class name, in any
323 # Only get public methods
324 my $method = Class::Inspector->methods( 'My::Class', 'public' );
330 The C<public> option will return only 'public' methods, as defined by the Perl
331 convention of prepending an underscore to any 'private' methods. The C<public>
332 option will effectively remove any methods that start with an underscore.
336 The C<private> options will return only 'private' methods, as defined by the
337 Perl convention of prepending an underscore to an private methods. The
338 C<private> option will effectively remove an method that do not start with an
341 B<Note: The C<public> and C<private> options are mutually exclusive>
345 C<methods> normally returns just the method name. Supplying the C<full> option
346 will cause the methods to be returned as the full names. That is, instead of
347 returning C<[ 'method1', 'method2', 'method3' ]>, you would instead get
348 C<[ 'Class::method1', 'AnotherClass::method2', 'Class::method3' ]>.
352 The C<expanded> option will cause a lot more information about method to be
353 returned. Instead of just the method name, you will instead get an array
354 reference containing the method name as a single combined name, ala C<full>,
355 the seperate class and method, and a CODE ref to the actual function ( if
356 available ). Please note that the function reference is not guarenteed to
357 be available. C<Class::Inspector> is intended at some later time, work
358 with modules that have some some of common run-time loader in place ( e.g
359 C<Autoloader> or C<Class::Autouse> for example.
361 The response from C<methods( 'Class', 'expanded' )> would look something like
365 [ 'Class::method1', 'Class', 'method1', \&Class::method1 ],
366 [ 'Another::method2', 'Another', 'method2', \&Another::method2 ],
367 [ 'Foo::bar', 'Foo', 'bar', \&Foo::bar ],
376 my $name = $class->_class( shift ) or return undef;
377 my @arguments = map { lc $_ } @_;
379 # Process the arguments to determine the options
381 foreach ( @arguments ) {
382 if ( $_ eq 'public' ) {
383 # Only get public methods
384 return undef if $options{private};
385 $options{public} = 1;
387 } elsif ( $_ eq 'private' ) {
388 # Only get private methods
389 return undef if $options{public};
390 $options{private} = 1;
392 } elsif ( $_ eq 'full' ) {
393 # Return the full method name
394 return undef if $options{expanded};
397 } elsif ( $_ eq 'expanded' ) {
398 # Returns class, method and function ref
399 return undef if $options{full};
400 $options{expanded} = 1;
403 # Unknown or unsupported options
408 # Only works if the class is loaded
409 return undef unless $class->loaded( $name );
411 # Get the super path ( not including UNIVERSAL )
412 # Rather than using Class::ISA, we'll use an inlined version
413 # that implements the same basic algorithm.
415 my @queue = ( $name );
416 my %seen = ( $name => 1 );
417 while ( my $cl = shift @queue ) {
419 unshift @queue, grep { ! $seen{$_}++ }
420 map { s/^::/main::/; s/\'/::/g; $_ }
424 # Find and merge the function names across the entire super path.
425 # Sort alphabetically and return.
427 foreach my $namespace ( @path ) {
428 my @functions = grep { ! $methods{$_} }
429 grep { /$RE_IDENTIFIER/o }
430 grep { defined &{"${namespace}::$_"} }
431 keys %{"${namespace}::"};
432 foreach ( @functions ) {
433 $methods{$_} = $namespace;
437 # Filter to public or private methods if needed
438 my @methodlist = sort keys %methods;
439 @methodlist = grep { ! /^\_/ } @methodlist if $options{public};
440 @methodlist = grep { /^\_/ } @methodlist if $options{private};
442 # Return in the correct format
443 @methodlist = map { "$methods{$_}::$_" } @methodlist if $options{full};
445 [ "$methods{$_}::$_", $methods{$_}, $_, \&{"$methods{$_}::$_"} ]
446 } @methodlist if $options{expanded};
455 #####################################################################
460 =head2 subclasses $class
462 The C<subclasses> static method will search then entire namespace (and thus
463 B<all> currently loaded classes) to find all classes that are subclasses
464 of the class provided as a the parameter.
466 The actual test will be done by calling C<isa> on the class as a static
467 method. (i.e. C<My::Class-E<gt>isa($class)>.
469 Returns a reference to a list of the loaded classes that match the class
470 provided, or false is none match, or C<undef> if the class name provided
477 my $name = $class->_class( shift ) or return undef;
479 # Prepare the search queue
481 my @queue = grep { $_ ne 'main' } $class->_subnames('');
483 my $c = shift(@queue); # c for class
484 if ( $class->_loaded($c) ) {
485 # At least one person has managed to misengineer
486 # a situation in which ->isa could die, even if the
487 # class is real. Trap these cases and just skip
488 # over that (bizarre) class. That would at limit
489 # problems with finding subclasses to only the
490 # modules that have broken ->isa implementation.
493 if ( $c->isa($name) ) {
494 # Add to the found list, but don't add the class itself
495 push @found, $c unless $c eq $name;
500 # Add any child namespaces to the head of the queue.
501 # This keeps the queue length shorted, and allows us
502 # not to have to do another sort at the end.
503 unshift @queue, map { "${c}::$_" } $class->_subnames($c);
506 @found ? \@found : '';
510 my ($class, $name) = @_;
513 substr($_, -2, 2, '') eq '::'
524 #####################################################################
525 # Children Related Methods
527 # These can go undocumented for now, until I decide if its best to
528 # just search the children in namespace only, or if I should do it via
531 # Find all the loaded classes below us
534 my $name = $class->_class(shift) or return ();
536 # Find all the Foo:: elements in our symbol table
538 map { "${name}::$_" } sort grep { s/::$// } keys %{"${name}::"};
541 # As above, but recursively
542 sub recursive_children {
544 my $name = $class->_class(shift) or return ();
545 my @children = ( $name );
547 # Do the search using a nicer, more memory efficient
548 # variant of actual recursion.
551 while ( my $namespace = $children[$i++] ) {
552 push @children, map { "${namespace}::$_" }
553 grep { ! /^::/ } # Ignore things like ::ISA::CACHE::
555 keys %{"${namespace}::"};
565 #####################################################################
568 # Checks and expands ( if needed ) a class name
571 my $name = shift or return '';
573 # Handle main shorthand
574 return 'main' if $name eq '::';
575 $name =~ s/\A::/main::/;
577 # Check the class name is valid
578 $name =~ /$RE_CLASS/o ? $name : '';
581 # Create a INC-specific filename, which always uses '/'
582 # regardless of platform.
585 my $name = $class->_class(shift) or return undef;
586 join( '/', split /(?:\'|::)/, $name ) . '.pm';
589 # Convert INC-specific file name to local file name
591 # Shortcut in the Unix case
592 return $_[1] if $UNIX;
594 # On other places, we have to deal with an unusual path that might look
595 # like C:/foo/bar.pm which doesn't fit ANY normal pattern.
596 # Putting it through splitpath/dir and back again seems to normalise
597 # it to a reasonable amount.
599 my $inc_name = shift or return undef;
600 my ($vol, $dir, $file) = File::Spec->splitpath( $inc_name );
601 $dir = File::Spec->catdir( File::Spec->splitdir( $dir || "" ) );
602 File::Spec->catpath( $vol, $dir, $file || "" );
611 Bugs should be reported via the CPAN bug tracker
613 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Class-Inspector>
615 For other issues, or commercial enhancement or support, contact the author.
619 Adam Kennedy E<lt>adamk@cpan.orgE<gt>
623 L<http://ali.as/>, L<Class::Handle>
627 Copyright 2002 - 2009 Adam Kennedy.
629 This program is free software; you can redistribute
630 it and/or modify it under the same terms as Perl itself.
632 The full text of the license can be found in the
633 LICENSE file included with this module.