--- /dev/null
+Revision history for Perl extension Class-Inspector
+
+1.36 2019-07-19 08:35:53 -0400
+ - Producton release identical to 1.35_01
+
+1.35_01 2019-07-18 12:00:22 -0400
+ - Fix bug in methods method that could cause it to modify @ISA (gh#11)
+
+1.34 2019-03-28 12:13:40 -0400
+ - Producton release identical to 1.33_01
+
+1.33_01 2019-03-27 23:30:09 -0400
+ - Fix compatability with Devel::Hide (gh#6, gh#8).
+
+1.32 2017-08-08 14:12:42 -0400
+ - The installed method now supports @INC hooks of any type
+ (coderef was supported as of 1.29, now arrayrefs and objects
+ are supported)
+ - Detect probably broken Perl on Cygwin in Makefile.PL (see gh#5)
+
+1.31 2016-11-25 09:33:47 -0500
+ - Migrated from Module::Install to Dist::Zilla and ExtUtils::MakeMaker
+ - Fixed meta for repository which was pointing to the wrong URL
+
+1.30 23 Nov 2016
+ - Moving to prod release
+
+1.29_02 23 Nov 2016
+ - Update metadata to point to github repository.
+ Plus some other minor dist meta tweaks.
+ - Note: planning on doing a migration from Module::Install
+ to ExtUtils::MakeMaker shortly AFTER the next production
+ release.
+
+1.29_01 22 Nov 2016
+ - Fix Makefile.PL to work with Perls without '.' in @INC
+ - Fix for the installed method when used with a PAR archive (rt#42846)
+ - Minor documentation fixes (grammar, spelling: rt#74481, rt#85356)
+
+1.28 Fri 19 Oct 2012
+ - No functional changes
+ - Updating to Module::Install::DSL 1.06
+
+1.27 Wed 25 Jan 2012
+ - Moving to prod release
+
+1.26_01 Tue 24 Jan 2012
+ - Updating to Module::Install::DSL 1.04
+ - Updating copyright year
+ - Remove usage of defined @{"X::ISA"} to avoid warnings in 5.15.7
+ and later Perl 5.16 (Tom Wyant)
+
+1.25 Thu 27 Jan 2011
+ - Updating to Module::Install::DSL 1.00
+ - Updating copyright year
+
+1.24 Tue 21 Apr 2009
+ - Updating Perl dependency to 5.006
+ - Updating to Module::Install::DSL 0.83
+ - Add the Class::Inspector::Functions interface.
+
+1.23 Mon 2 Jun 2008
+ - No functional changes
+ - Updating to Module::Install 0.75
+ - Correcting the location of the author tests
+
+1.22 Sat 1 Mar 2008
+ - 1.21_01 tested ok, moving to production version
+ - No changes
+
+1.21_01 Tue 12 Feb 2008
+ - Adding experimental support for utf8 methods
+ (as per http://rt.cpan.org/Public/Bug/Display.html?id=28796)
+
+1.20 Tue 12 Feb 2008
+ - CPAN Testers results look good for 1.19_01,
+ converting to a production release.
+
+1.19_01 Mon 11 Feb 2008
+ - Bug fix to adapt to changes to File::Spec
+
+1.18 Thu 8 Nov 2007
+ - Incremental release, no functional changes
+ - Updated to Module::Install 0.68
+ (This brings META.yml to the current version)
+ - Updated versions of the automated tests that
+ were causing CPAN Testers failures.
+
+1.17 Mon 6 Aug 2007
+ - Classes with leading numbers after the first :: are permitted
+ - Removing some old cruft from the tests
+ - Updated to Module::Install 0.65
+
+1.16 Wed 10 May 2006
+ - This release contains only build-time changes
+ - AutoInstall is only needed for options, so remove auto_install
+
+1.15 Sun 7 May 2006
+ - This release contains only build-time changes
+ - Upgrading to Module::Install 0.62
+
+1.14 Sun 8 Apr 2006
+ - This release contains only build-time changes
+ - Moved from older CVS to newer SVN repository
+ - Upgraded to Module::Install 0.61
+
+1.13 Wed Sep 28 2005
+ - Fixed a minor POD bug in the synopsis
+
+1.12 Fri Sep 9 2005
+ - Added a fix for classes with insanely broken ->isa methods
+ that cause Perl to die.
+
+1.11 Tue Sep 6 2005
+ - It occured to me after I added ->find that what it _really_ is
+ is a way to find all the subclasses, but then include the class
+ itself in the returned list. This method makes much more sense
+ it I don't return the class itself, and rename it ->subclasses
+ - Fixed broken Makefile.PL
+
+1.10 Mon Sep 5 2005
+ - Added the ->find method
+ - Cleaned up and reorganised the POD
+ - Made sure all return conditions are documented properly
+ - Converted to Module::Install
+
+1.09 skipped
+
+1.08 Tue Feb 15 2005
+ - Removing braindead Build.PL
+
+1.07 Thu Nov 18 2004
+ - Improved the speed (slightly, and only in positive cases) and accuracy of ->loaded.
+ - It now checks for some additional clues before returning false.
+
+1.06 Wed Jul 21 2004
+ - Fixed a major Win32 bug
+
+1.05 Mon Jul 19 2004
+ - Inlined a better version of self_and_super_class
+ - Removed Class::ISA as a dependency
+
+1.04 Tue Mar 23 2004
+ - Apparently on Windows @INC/%INC uses Unix style backslashes
+ Updated to handle this fact.
+
+1.03 Sun Dec 14 2003
+ - Fixed an infinite loop bug in recursive_children
+
+1.02 Sun Dec 14 2003
+ - recursive children ignores ::ISA::CACHE::
+ - Minor code tweaks
+
+1.01 Mon Nov 10 2003
+ - Symbol table entries due to overloads and anonymous subs
+ are filtered from the results correctly.
+ - Did a large amount of code cleaning and optomising
+
+1.0 Sat Dec 21 13:31:21 2002
+ - Converted to use File::Spec
+
+0.2 Tue May 28 18:47:00 2002
+ - Added options for ->methods
+
+0.1 Thu May 23 20:09:55 2002
+ - original version
--- /dev/null
+This is the Perl distribution Class-Inspector.
+
+Installing Class-Inspector is straightforward.
+
+## Installation with cpanm
+
+If you have cpanm, you only need one line:
+
+ % cpanm Class::Inspector
+
+If it does not have permission to install modules to the current perl, cpanm
+will automatically set up and install to a local::lib in your home directory.
+See the local::lib documentation (https://metacpan.org/pod/local::lib) for
+details on enabling it in your environment.
+
+## Installing with the CPAN shell
+
+Alternatively, if your CPAN shell is set up, you should just be able to do:
+
+ % cpan Class::Inspector
+
+## Manual installation
+
+As a last resort, you can manually install it. Download the tarball, untar it,
+install configure prerequisites (see below), then build it:
+
+ % perl Makefile.PL
+ % make && make test
+
+Then install it:
+
+ % make install
+
+On Windows platforms, you should use `dmake` or `nmake`, instead of `make`.
+
+If your perl is system-managed, you can create a local::lib in your home
+directory to install modules to. For details, see the local::lib documentation:
+https://metacpan.org/pod/local::lib
+
+The prerequisites of this distribution will also have to be installed manually. The
+prerequisites are listed in one of the files: `MYMETA.yml` or `MYMETA.json` generated
+by running the manual build process described above.
+
+## Configure Prerequisites
+
+This distribution requires other modules to be installed before this
+distribution's installer can be run. They can be found under the
+"configure_requires" key of META.yml or the
+"{prereqs}{configure}{requires}" key of META.json.
+
+## Other Prerequisites
+
+This distribution may require additional modules to be installed after running
+Makefile.PL.
+Look for prerequisites in the following phases:
+
+* to run make, PHASE = build
+* to use the module code itself, PHASE = runtime
+* to run tests, PHASE = test
+
+They can all be found in the "PHASE_requires" key of MYMETA.yml or the
+"{prereqs}{PHASE}{requires}" key of MYMETA.json.
+
+## Documentation
+
+Class-Inspector documentation is available as POD.
+You can run `perldoc` from a shell to read the documentation:
+
+ % perldoc Class::Inspector
+
+For more information on installing Perl modules via CPAN, please see:
+https://www.cpan.org/modules/INSTALL.html
--- /dev/null
+This software is copyright (c) 2002-2019 by Adam Kennedy.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+Terms of the Perl programming language system itself
+
+a) the GNU General Public License as published by the Free
+ Software Foundation; either version 1, or (at your option) any
+ later version, or
+b) the "Artistic License"
+
+--- The GNU General Public License, Version 1, February 1989 ---
+
+This software is Copyright (c) 2002-2019 by Adam Kennedy.
+
+This is free software, licensed under:
+
+ The GNU General Public License, Version 1, February 1989
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 1, February 1989
+
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The license agreements of most software companies try to keep users
+at the mercy of those companies. By contrast, our General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. The
+General Public License applies to the Free Software Foundation's
+software and to any other program whose authors commit to using it.
+You can use it for your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Specifically, the General Public License is designed to make
+sure that you have the freedom to give away or sell copies of free
+software, that you receive source code or can get it if you want it,
+that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of a such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must tell them their rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any program or other work which
+contains a notice placed by the copyright holder saying it may be
+distributed under the terms of this General Public License. The
+"Program", below, refers to any such program or work, and a "work based
+on the Program" means either the Program or any work containing the
+Program or a portion of it, either verbatim or with modifications. Each
+licensee is addressed as "you".
+
+ 1. You may copy and distribute verbatim copies of the Program's source
+code as you receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice and
+disclaimer of warranty; keep intact all the notices that refer to this
+General Public License and to the absence of any warranty; and give any
+other recipients of the Program a copy of this General Public License
+along with the Program. You may charge a fee for the physical act of
+transferring a copy.
+
+ 2. You may modify your copy or copies of the Program or any portion of
+it, and copy and distribute such modifications under the terms of Paragraph
+1 above, provided that you also do the following:
+
+ a) cause the modified files to carry prominent notices stating that
+ you changed the files and the date of any change; and
+
+ b) cause the whole of any work that you distribute or publish, that
+ in whole or in part contains the Program or any part thereof, either
+ with or without modifications, to be licensed at no charge to all
+ third parties under the terms of this General Public License (except
+ that you may choose to grant warranty protection to some or all
+ third parties, at your option).
+
+ c) If the modified program normally reads commands interactively when
+ run, you must cause it, when started running for such interactive use
+ in the simplest and most usual way, to print or display an
+ announcement including an appropriate copyright notice and a notice
+ that there is no warranty (or else, saying that you provide a
+ warranty) and that users may redistribute the program under these
+ conditions, and telling the user how to view a copy of this General
+ Public License.
+
+ d) You may charge a fee for the physical act of transferring a
+ copy, and you may at your option offer warranty protection in
+ exchange for a fee.
+
+Mere aggregation of another independent work with the Program (or its
+derivative) on a volume of a storage or distribution medium does not bring
+the other work under the scope of these terms.
+
+ 3. You may copy and distribute the Program (or a portion or derivative of
+it, under Paragraph 2) in object code or executable form under the terms of
+Paragraphs 1 and 2 above provided that you also do one of the following:
+
+ a) accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ b) accompany it with a written offer, valid for at least three
+ years, to give any third party free (except for a nominal charge
+ for the cost of distribution) a complete machine-readable copy of the
+ corresponding source code, to be distributed under the terms of
+ Paragraphs 1 and 2 above; or,
+
+ c) accompany it with the information you received as to where the
+ corresponding source code may be obtained. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form alone.)
+
+Source code for a work means the preferred form of the work for making
+modifications to it. For an executable file, complete source code means
+all the source code for all modules it contains; but, as a special
+exception, it need not include source code for modules which are standard
+libraries that accompany the operating system on which the executable
+file runs, or for standard header files or definitions files that
+accompany that operating system.
+
+ 4. You may not copy, modify, sublicense, distribute or transfer the
+Program except as expressly provided under this General Public License.
+Any attempt otherwise to copy, modify, sublicense, distribute or transfer
+the Program is void, and will automatically terminate your rights to use
+the Program under this License. However, parties who have received
+copies, or rights to use copies, from you under this General Public
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+ 5. By copying, distributing or modifying the Program (or any work based
+on the Program) you indicate your acceptance of this license to do so,
+and all its terms and conditions.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the original
+licensor to copy, distribute or modify the Program subject to these
+terms and conditions. You may not impose any further restrictions on the
+recipients' exercise of the rights granted herein.
+
+ 7. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of the license which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+the license, you may choose any version ever published by the Free Software
+Foundation.
+
+ 8. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to humanity, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+ To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively convey
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 1, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the
+appropriate parts of the General Public License. Of course, the
+commands you use may be called something other than `show w' and `show
+c'; they could even be mouse-clicks or menu items--whatever suits your
+program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ program `Gnomovision' (a program to direct compilers to make passes
+ at assemblers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+--- The Artistic License 1.0 ---
+
+This software is Copyright (c) 2002-2019 by Adam Kennedy.
+
+This is free software, licensed under:
+
+ The Artistic License 1.0
+
+The Artistic License
+
+Preamble
+
+The intent of this document is to state the conditions under which a Package
+may be copied, such that the Copyright Holder maintains some semblance of
+artistic control over the development of the package, while giving the users of
+the package the right to use and distribute the Package in a more-or-less
+customary fashion, plus the right to make reasonable modifications.
+
+Definitions:
+
+ - "Package" refers to the collection of files distributed by the Copyright
+ Holder, and derivatives of that collection of files created through
+ textual modification.
+ - "Standard Version" refers to such a Package if it has not been modified,
+ or has been modified in accordance with the wishes of the Copyright
+ Holder.
+ - "Copyright Holder" is whoever is named in the copyright or copyrights for
+ the package.
+ - "You" is you, if you're thinking about copying or distributing this Package.
+ - "Reasonable copying fee" is whatever you can justify on the basis of media
+ cost, duplication charges, time of people involved, and so on. (You will
+ not be required to justify it to the Copyright Holder, but only to the
+ computing community at large as a market that must bear the fee.)
+ - "Freely Available" means that no fee is charged for the item itself, though
+ there may be fees involved in handling the item. It also means that
+ recipients of the item may redistribute it under the same conditions they
+ received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications derived
+from the Public Domain or from the Copyright Holder. A Package modified in such
+a way shall still be considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided that
+you insert a prominent notice in each changed file stating how and when you
+changed that file, and provided that you do at least ONE of the following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or an
+ equivalent medium, or placing the modifications on a major archive site
+ such as ftp.uu.net, or by allowing the Copyright Holder to include your
+ modifications in the Standard Version of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict with
+ standard executables, which must also be provided, and provide a separate
+ manual page for each non-standard executable that clearly documents how it
+ differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+4. You may distribute the programs of this Package in object code or executable
+form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where to
+ get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of the Package
+ with your modifications.
+
+ c) accompany any non-standard executables with their corresponding Standard
+ Version executables, giving the non-standard executables non-standard
+ names, and clearly documenting the differences in manual pages (or
+ equivalent), together with instructions on where to get the Standard
+ Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+5. You may charge a reasonable copying fee for any distribution of this
+Package. You may charge any fee you choose for support of this Package. You
+may not charge a fee for this Package itself. However, you may distribute this
+Package in aggregate with other (possibly commercial) programs as part of a
+larger (possibly commercial) software distribution provided that you do not
+advertise this Package as a product of your own.
+
+6. The scripts and library files supplied as input to or produced as output
+from the programs of this Package do not automatically fall under the copyright
+of this Package, but belong to whomever generated them, and may be sold
+commercially, and may be aggregated with this Package.
+
+7. C or perl subroutines supplied by you and linked into this Package shall not
+be considered part of this Package.
+
+8. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+The End
+
--- /dev/null
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.012.
+Changes
+INSTALL
+LICENSE
+MANIFEST
+META.json
+META.yml
+Makefile.PL
+README
+author.yml
+dist.ini
+lib/Class/Inspector.pm
+lib/Class/Inspector/Functions.pm
+maint/cip-before-install
+maint/cip-test
+perlcriticrc
+t/00_diag.t
+t/01_use.t
+t/class_inspector.t
+t/class_inspector__devel_hide.t
+t/class_inspector__inc_to_local.t
+t/class_inspector_functions.t
+xt/author/critic.t
+xt/author/eol.t
+xt/author/no_tabs.t
+xt/author/pod.t
+xt/author/pod_coverage.t
+xt/author/pod_spelling_common.t
+xt/author/strict.t
+xt/author/version.t
+xt/release/fixme.t
--- /dev/null
+{
+ "abstract" : "Get information about a class and its structure",
+ "author" : [
+ "Graham Ollis <plicease@cpan.org>",
+ "Adam Kennedy <adamk@cpan.org>"
+ ],
+ "dynamic_config" : 0,
+ "generated_by" : "Dist::Zilla version 6.012, CPAN::Meta::Converter version 2.150010",
+ "license" : [
+ "perl_5"
+ ],
+ "meta-spec" : {
+ "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
+ "version" : 2
+ },
+ "name" : "Class-Inspector",
+ "prereqs" : {
+ "configure" : {
+ "requires" : {
+ "ExtUtils::MakeMaker" : "0",
+ "perl" : "5.008"
+ }
+ },
+ "develop" : {
+ "requires" : {
+ "FindBin" : "0",
+ "Test2::Tools::PerlCritic" : "0",
+ "Test::EOL" : "0",
+ "Test::Fixme" : "0.07",
+ "Test::More" : "0.98",
+ "Test::NoTabs" : "0",
+ "Test::Pod" : "0",
+ "Test::Pod::Coverage" : "0",
+ "Test::Pod::Spelling::CommonMistakes" : "0",
+ "Test::Strict" : "0",
+ "YAML" : "0"
+ }
+ },
+ "runtime" : {
+ "requires" : {
+ "File::Spec" : "0.80",
+ "base" : "0",
+ "perl" : "5.008"
+ }
+ },
+ "test" : {
+ "requires" : {
+ "Test::More" : "0.98",
+ "perl" : "5.008"
+ }
+ }
+ },
+ "provides" : {
+ "Class::Inspector" : {
+ "file" : "lib/Class/Inspector.pm",
+ "version" : "1.36"
+ },
+ "Class::Inspector::Functions" : {
+ "file" : "lib/Class/Inspector/Functions.pm",
+ "version" : "1.36"
+ }
+ },
+ "release_status" : "stable",
+ "resources" : {
+ "bugtracker" : {
+ "web" : "https://github.com/plicease/Class-Inspector/issues"
+ },
+ "homepage" : "https://metacpan.org/pod/Class::Inspector",
+ "repository" : {
+ "type" : "git",
+ "url" : "git://github.com/plicease/Class-Inspector.git",
+ "web" : "https://github.com/plicease/Class-Inspector"
+ }
+ },
+ "version" : "1.36",
+ "x_contributors" : [
+ "Adam Kennedy <adamk@cpan.org>",
+ "Graham Ollis <plicease@cpan.org>",
+ "Tom Wyant",
+ "Steffen M\u00fcller",
+ "Kivanc Yazan (KYZN)"
+ ],
+ "x_generated_by_perl" : "v5.28.1",
+ "x_serialization_backend" : "Cpanel::JSON::XS version 4.12",
+ "x_use_unsafe_inc" : 0
+}
+
--- /dev/null
+---
+abstract: 'Get information about a class and its structure'
+author:
+ - 'Graham Ollis <plicease@cpan.org>'
+ - 'Adam Kennedy <adamk@cpan.org>'
+build_requires:
+ Test::More: '0.98'
+ perl: '5.008'
+configure_requires:
+ ExtUtils::MakeMaker: '0'
+ perl: '5.008'
+dynamic_config: 0
+generated_by: 'Dist::Zilla version 6.012, CPAN::Meta::Converter version 2.150010'
+license: perl
+meta-spec:
+ url: http://module-build.sourceforge.net/META-spec-v1.4.html
+ version: '1.4'
+name: Class-Inspector
+provides:
+ Class::Inspector:
+ file: lib/Class/Inspector.pm
+ version: '1.36'
+ Class::Inspector::Functions:
+ file: lib/Class/Inspector/Functions.pm
+ version: '1.36'
+requires:
+ File::Spec: '0.80'
+ base: '0'
+ perl: '5.008'
+resources:
+ bugtracker: https://github.com/plicease/Class-Inspector/issues
+ homepage: https://metacpan.org/pod/Class::Inspector
+ repository: git://github.com/plicease/Class-Inspector.git
+version: '1.36'
+x_contributors:
+ - 'Adam Kennedy <adamk@cpan.org>'
+ - 'Graham Ollis <plicease@cpan.org>'
+ - 'Tom Wyant'
+ - 'Steffen Müller'
+ - 'Kivanc Yazan (KYZN)'
+x_generated_by_perl: v5.28.1
+x_serialization_backend: 'YAML::Tiny version 1.73'
+x_use_unsafe_inc: 0
--- /dev/null
+BEGIN {
+ use strict; use warnings;
+ {
+ my $fn = 'Class/Inspector.pm';
+ unless(index('lib/Class/Inspector.pm', $fn) == index('lib/Class/Inspector.pm', 'Class/Inspector.pm'))
+ {
+ print "I believe you have a broken Perl.\n";
+ print "Please see https://github.com/plicease/Class-Inspector/issues/5\n";
+ print "If you believe this diagnostic is mistaken, you can edit the Makefile.PL and comment out the logic that determins this.\n";
+ print "If you believe this diagnostic is mistaken, feel free to comment on the issue above.\n";
+ exit;
+ }
+ }
+ unless(eval q{ use 5.008; 1}) {
+ print "Perl 5.008 or better required\n";
+ exit;
+ }
+}
+# This file was automatically generated by Dist::Zilla::Plugin::Author::Plicease::MakeMaker v2.37.
+use strict;
+use warnings;
+use 5.008;
+use ExtUtils::MakeMaker;
+
+my %WriteMakefileArgs = (
+ "ABSTRACT" => "Get information about a class and its structure",
+ "AUTHOR" => "Graham Ollis <plicease\@cpan.org>, Adam Kennedy <adamk\@cpan.org>",
+ "CONFIGURE_REQUIRES" => {
+ "ExtUtils::MakeMaker" => 0
+ },
+ "DISTNAME" => "Class-Inspector",
+ "LICENSE" => "perl",
+ "MIN_PERL_VERSION" => "5.008",
+ "NAME" => "Class::Inspector",
+ "PM" => {
+ "lib/Class/Inspector.pm" => "\$(INST_LIB)/Class/Inspector.pm",
+ "lib/Class/Inspector/Functions.pm" => "\$(INST_LIB)/Class/Inspector/Functions.pm"
+ },
+ "PREREQ_PM" => {
+ "File::Spec" => "0.80",
+ "base" => 0
+ },
+ "TEST_REQUIRES" => {
+ "Test::More" => "0.98"
+ },
+ "VERSION" => "1.36",
+ "test" => {
+ "TESTS" => "t/*.t"
+ }
+);
+
+my %FallbackPrereqs = (
+ "File::Spec" => "0.80",
+ "Test::More" => "0.98",
+ "base" => 0
+);
+
+unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
+ delete $WriteMakefileArgs{TEST_REQUIRES};
+ delete $WriteMakefileArgs{BUILD_REQUIRES};
+ $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
+}
+
+delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
+ unless eval { ExtUtils::MakeMaker->VERSION(6.52) };
+
+WriteMakefile(%WriteMakefileArgs);
\ No newline at end of file
--- /dev/null
+NAME
+
+ Class::Inspector - Get information about a class and its structure
+
+VERSION
+
+ version 1.36
+
+SYNOPSIS
+
+ use Class::Inspector;
+
+ # Is a class installed and/or loaded
+ Class::Inspector->installed( 'Foo::Class' );
+ Class::Inspector->loaded( 'Foo::Class' );
+
+ # Filename related information
+ Class::Inspector->filename( 'Foo::Class' );
+ Class::Inspector->resolved_filename( 'Foo::Class' );
+
+ # Get subroutine related information
+ Class::Inspector->functions( 'Foo::Class' );
+ Class::Inspector->function_refs( 'Foo::Class' );
+ Class::Inspector->function_exists( 'Foo::Class', 'bar' );
+ Class::Inspector->methods( 'Foo::Class', 'full', 'public' );
+
+ # Find all loaded subclasses or something
+ Class::Inspector->subclasses( 'Foo::Class' );
+
+DESCRIPTION
+
+ Class::Inspector allows you to get information about a loaded class.
+ Most or all of this information can be found in other ways, but they
+ aren't always very friendly, and usually involve a relatively high
+ level of Perl wizardry, or strange and unusual looking code.
+ Class::Inspector attempts to provide an easier, more friendly interface
+ to this information.
+
+METHODS
+
+ installed
+
+ my $bool = Class::Inspector->installed($class);
+
+ The installed static method tries to determine if a class is installed
+ on the machine, or at least available to Perl. It does this by wrapping
+ around resolved_filename.
+
+ Returns true if installed/available, false if the class is not
+ installed, or undef if the class name is invalid.
+
+ loaded
+
+ my $bool = Class::Inspector->loaded($class);
+
+ The loaded static method tries to determine if a class is loaded by
+ looking for symbol table entries.
+
+ This method it uses to determine this will work even if the class does
+ not have its own file, but is contained inside a single file with
+ multiple classes in it. Even in the case of some sort of run-time
+ loading class being used, these typically leave some trace in the
+ symbol table, so an Autoload or Class::Autouse-based class should
+ correctly appear loaded.
+
+ Returns true if the class is loaded, false if not, or undef if the
+ class name is invalid.
+
+ filename
+
+ my $filename = Class::Inspector->filename($class);
+
+ For a given class, returns the base filename for the class. This will
+ NOT be a fully resolved filename, just the part of the filename BELOW
+ the @INC entry.
+
+ print Class->filename( 'Foo::Bar' );
+ > Foo/Bar.pm
+
+ This filename will be returned with the right separator for the local
+ platform, and should work on all platforms.
+
+ Returns the filename on success or undef if the class name is invalid.
+
+ resolved_filename
+
+ my $filename = Class::Inspector->resolved_filename($class);
+ my $filename = Class::Inspector->resolved_filename($class, @try_first);
+
+ For a given class, the resolved_filename static method returns the
+ fully resolved filename for a class. That is, the file that the class
+ would be loaded from.
+
+ This is not necessarily the file that the class WAS loaded from, as the
+ value returned is determined each time it runs, and the @INC include
+ path may change.
+
+ To get the actual file for a loaded class, see the loaded_filename
+ method.
+
+ Returns the filename for the class, or undef if the class name is
+ invalid.
+
+ loaded_filename
+
+ my $filename = Class::Inspector->loaded_filename($class);
+
+ For a given loaded class, the loaded_filename static method determines
+ (via the %INC hash) the name of the file that it was originally loaded
+ from.
+
+ Returns a resolved file path, or false if the class did not have it's
+ own file.
+
+ functions
+
+ my $arrayref = Class::Inspector->functions($class);
+
+ For a loaded class, the functions static method returns a list of the
+ names of all the functions in the classes immediate namespace.
+
+ Note that this is not the METHODS of the class, just the functions.
+
+ Returns a reference to an array of the function names on success, or
+ undef if the class name is invalid or the class is not loaded.
+
+ function_refs
+
+ my $arrayref = Class::Inspector->function_refs($class);
+
+ For a loaded class, the function_refs static method returns references
+ to all the functions in the classes immediate namespace.
+
+ Note that this is not the METHODS of the class, just the functions.
+
+ Returns a reference to an array of CODE refs of the functions on
+ success, or undef if the class is not loaded.
+
+ function_exists
+
+ my $bool = Class::Inspector->function_exists($class, $functon);
+
+ Given a class and function name the function_exists static method will
+ check to see if the function exists in the class.
+
+ Note that this is as a function, not as a method. To see if a method
+ exists for a class, use the can method for any class or object.
+
+ Returns true if the function exists, false if not, or undef if the
+ class or function name are invalid, or the class is not loaded.
+
+ methods
+
+ my $arrayref = Class::Inspector->methods($class, @options);
+
+ For a given class name, the methods static method will returns ALL the
+ methods available to that class. This includes all methods available
+ from every class up the class' @ISA tree.
+
+ Returns a reference to an array of the names of all the available
+ methods on success, or undef if the class name is invalid or the class
+ is not loaded.
+
+ A number of options are available to the methods method that will alter
+ the results returned. These should be listed after the class name, in
+ any order.
+
+ # Only get public methods
+ my $method = Class::Inspector->methods( 'My::Class', 'public' );
+
+ public
+
+ The public option will return only 'public' methods, as defined by
+ the Perl convention of prepending an underscore to any 'private'
+ methods. The public option will effectively remove any methods that
+ start with an underscore.
+
+ private
+
+ The private options will return only 'private' methods, as defined by
+ the Perl convention of prepending an underscore to an private
+ methods. The private option will effectively remove an method that do
+ not start with an underscore.
+
+ Note: The public and private options are mutually exclusive
+
+ full
+
+ methods normally returns just the method name. Supplying the full
+ option will cause the methods to be returned as the full names. That
+ is, instead of returning [ 'method1', 'method2', 'method3' ], you
+ would instead get [ 'Class::method1', 'AnotherClass::method2',
+ 'Class::method3' ].
+
+ expanded
+
+ The expanded option will cause a lot more information about method to
+ be returned. Instead of just the method name, you will instead get an
+ array reference containing the method name as a single combined name,
+ a la full, the separate class and method, and a CODE ref to the
+ actual function ( if available ). Please note that the function
+ reference is not guaranteed to be available. Class::Inspector is
+ intended at some later time, to work with modules that have some kind
+ of common run-time loader in place ( e.g Autoloader or Class::Autouse
+ for example.
+
+ The response from methods( 'Class', 'expanded' ) would look something
+ like the following.
+
+ [
+ [ 'Class::method1', 'Class', 'method1', \&Class::method1 ],
+ [ 'Another::method2', 'Another', 'method2', \&Another::method2 ],
+ [ 'Foo::bar', 'Foo', 'bar', \&Foo::bar ],
+ ]
+
+ subclasses
+
+ my $arrayref = Class::Inspector->subclasses($class);
+
+ The subclasses static method will search then entire namespace (and
+ thus all currently loaded classes) to find all classes that are
+ subclasses of the class provided as a the parameter.
+
+ The actual test will be done by calling isa on the class as a static
+ method. (i.e. My::Class->isa($class).
+
+ Returns a reference to a list of the loaded classes that match the
+ class provided, or false is none match, or undef if the class name
+ provided is invalid.
+
+SEE ALSO
+
+ http://ali.as/, Class::Handle, Class::Inspector::Functions
+
+AUTHOR
+
+ Original author: Adam Kennedy <adamk@cpan.org>
+
+ Current maintainer: Graham Ollis <plicease@cpan.org>
+
+ Contributors:
+
+ Tom Wyant
+
+ Steffen Müller
+
+ Kivanc Yazan (KYZN)
+
+COPYRIGHT AND LICENSE
+
+ This software is copyright (c) 2002-2019 by Adam Kennedy.
+
+ This is free software; you can redistribute it and/or modify it under
+ the same terms as the Perl 5 programming language system itself.
+
--- /dev/null
+---
+pod_spelling_system:
+ skip: 0
+ stopwords:
+ - Müller
+ - Steffen
+ - Wyant
+
+
+pod_coverage:
+ skip: 0
+ private:
+ - Class::Inspector#children
+ - Class::Inspector#recursive_children
+ - Class::Inspector::Functions
--- /dev/null
+name = Class-Inspector
+author = Graham Ollis <plicease@cpan.org>
+author = Adam Kennedy <adamk@cpan.org>
+license = Perl_5
+copyright_holder = Adam Kennedy
+copyright_year = 2002-2019
+version = 1.36
+
+[@Author::Plicease]
+:version = 2.37
+travis_status = 1
+release_tests = 1
+
+preamble = | {
+preamble = | my $fn = 'Class/Inspector.pm';
+preamble = | unless(index('lib/Class/Inspector.pm', $fn) == index('lib/Class/Inspector.pm', 'Class/Inspector.pm'))
+preamble = | {
+preamble = | print "I believe you have a broken Perl.\n";
+preamble = | print "Please see https://github.com/plicease/Class-Inspector/issues/5\n";
+preamble = | print "If you believe this diagnostic is mistaken, you can edit the Makefile.PL and comment out the logic that determins this.\n";
+preamble = | print "If you believe this diagnostic is mistaken, feel free to comment on the issue above.\n";
+preamble = | exit;
+preamble = | }
+preamble = | }
+
+[Prereqs / TestPrereqs]
+-phase = test
+; TODO: this gets overridden with 0.94
+Test::More = 0.47
+
+[Prereqs]
+File::Spec = 0.80
+
+[RemovePrereqs]
+; comes with Perl 5.6.0 or better
+remove = strict
+remove = warnings
+remove = vars
+remove = constant
+remove = utf8
+remove = Exporter
+
+; optional test dep
+remove = Devel::Hide
+
+[Author::Plicease::Upload]
+cpan = 1
+
+[Author::Plicease::Thanks]
+current = Graham Ollis <plicease@cpan.org>
+original = Adam Kennedy <adamk@cpan.org>
+contributor = Tom Wyant
+contributor = Steffen Müller
+contributor = Kivanc Yazan (KYZN)
+
+[MetaProvides::Package]
+
+[PruneFiles]
+filename = xt/release/changes.t
+; some unicode issue needs to be resolved:
+filename = xt/author/pod_spelling_system.t
--- /dev/null
+package Class::Inspector;
+
+use 5.006;
+# We don't want to use strict refs anywhere in this module, since we do a
+# lot of things in here that aren't strict refs friendly.
+use strict qw{vars subs};
+use warnings;
+use File::Spec ();
+
+# ABSTRACT: Get information about a class and its structure
+our $VERSION = '1.36'; # VERSION
+
+
+# If Unicode is available, enable it so that the
+# pattern matches below match unicode method names.
+# We can safely ignore any failure here.
+BEGIN {
+ local $@;
+ eval {
+ require utf8;
+ utf8->import;
+ };
+}
+
+# Predefine some regexs
+our $RE_IDENTIFIER = qr/\A[^\W\d]\w*\z/s;
+our $RE_CLASS = qr/\A[^\W\d]\w*(?:(?:\'|::)\w+)*\z/s;
+
+# Are we on something Unix-like?
+our $UNIX = !! ( $File::Spec::ISA[0] eq 'File::Spec::Unix' );
+
+
+#####################################################################
+# Basic Methods
+
+
+sub _resolved_inc_handler {
+ my $class = shift;
+ my $filename = $class->_inc_filename(shift) or return undef;
+
+ foreach my $inc ( @INC ) {
+ my $ref = ref $inc;
+ if($ref eq 'CODE') {
+ my @ret = $inc->($inc, $filename);
+ if(@ret == 1 && ! defined $ret[0]) {
+ # do nothing.
+ } elsif(@ret) {
+ return 1;
+ }
+ }
+ elsif($ref eq 'ARRAY' && ref($inc->[0]) eq 'CODE') {
+ my @ret = $inc->[0]->($inc, $filename);
+ if(@ret) {
+ return 1;
+ }
+ }
+ elsif($ref && eval { $inc->can('INC') }) {
+ my @ret = $inc->INC($filename);
+ if(@ret) {
+ return 1;
+ }
+ }
+ }
+
+ '';
+}
+
+sub installed {
+ my $class = shift;
+ !! ($class->loaded_filename($_[0]) or $class->resolved_filename($_[0]) or $class->_resolved_inc_handler($_[0]));
+}
+
+
+sub loaded {
+ my $class = shift;
+ my $name = $class->_class(shift) or return undef;
+ $class->_loaded($name);
+}
+
+sub _loaded {
+ my $class = shift;
+ my $name = shift;
+
+ # Handle by far the two most common cases
+ # This is very fast and handles 99% of cases.
+ return 1 if defined ${"${name}::VERSION"};
+ return 1 if @{"${name}::ISA"};
+
+ # Are there any symbol table entries other than other namespaces
+ foreach ( keys %{"${name}::"} ) {
+ next if substr($_, -2, 2) eq '::';
+ return 1 if defined &{"${name}::$_"};
+ }
+
+ # No functions, and it doesn't have a version, and isn't anything.
+ # As an absolute last resort, check for an entry in %INC
+ my $filename = $class->_inc_filename($name);
+ return 1 if defined $INC{$filename};
+
+ '';
+}
+
+
+sub filename {
+ my $class = shift;
+ my $name = $class->_class(shift) or return undef;
+ File::Spec->catfile( split /(?:\'|::)/, $name ) . '.pm';
+}
+
+
+sub resolved_filename {
+ my $class = shift;
+ my $filename = $class->_inc_filename(shift) or return undef;
+ my @try_first = @_;
+
+ # Look through the @INC path to find the file
+ foreach ( @try_first, @INC ) {
+ my $full = "$_/$filename";
+ next unless -e $full;
+ return $UNIX ? $full : $class->_inc_to_local($full);
+ }
+
+ # File not found
+ '';
+}
+
+
+sub loaded_filename {
+ my $class = shift;
+ my $filename = $class->_inc_filename(shift);
+ $UNIX ? $INC{$filename} : $class->_inc_to_local($INC{$filename});
+}
+
+
+
+
+
+#####################################################################
+# Sub Related Methods
+
+
+sub functions {
+ my $class = shift;
+ my $name = $class->_class(shift) or return undef;
+ return undef unless $class->loaded( $name );
+
+ # Get all the CODE symbol table entries
+ my @functions = sort grep { /$RE_IDENTIFIER/o }
+ grep { defined &{"${name}::$_"} }
+ keys %{"${name}::"};
+ \@functions;
+}
+
+
+sub function_refs {
+ my $class = shift;
+ my $name = $class->_class(shift) or return undef;
+ return undef unless $class->loaded( $name );
+
+ # Get all the CODE symbol table entries, but return
+ # the actual CODE refs this time.
+ my @functions = map { \&{"${name}::$_"} }
+ sort grep { /$RE_IDENTIFIER/o }
+ grep { defined &{"${name}::$_"} }
+ keys %{"${name}::"};
+ \@functions;
+}
+
+
+sub function_exists {
+ my $class = shift;
+ my $name = $class->_class( shift ) or return undef;
+ my $function = shift or return undef;
+
+ # Only works if the class is loaded
+ return undef unless $class->loaded( $name );
+
+ # Does the GLOB exist and its CODE part exist
+ defined &{"${name}::$function"};
+}
+
+
+sub methods {
+ my $class = shift;
+ my $name = $class->_class( shift ) or return undef;
+ my @arguments = map { lc $_ } @_;
+
+ # Process the arguments to determine the options
+ my %options = ();
+ foreach ( @arguments ) {
+ if ( $_ eq 'public' ) {
+ # Only get public methods
+ return undef if $options{private};
+ $options{public} = 1;
+
+ } elsif ( $_ eq 'private' ) {
+ # Only get private methods
+ return undef if $options{public};
+ $options{private} = 1;
+
+ } elsif ( $_ eq 'full' ) {
+ # Return the full method name
+ return undef if $options{expanded};
+ $options{full} = 1;
+
+ } elsif ( $_ eq 'expanded' ) {
+ # Returns class, method and function ref
+ return undef if $options{full};
+ $options{expanded} = 1;
+
+ } else {
+ # Unknown or unsupported options
+ return undef;
+ }
+ }
+
+ # Only works if the class is loaded
+ return undef unless $class->loaded( $name );
+
+ # Get the super path ( not including UNIVERSAL )
+ # Rather than using Class::ISA, we'll use an inlined version
+ # that implements the same basic algorithm.
+ my @path = ();
+ my @queue = ( $name );
+ my %seen = ( $name => 1 );
+ while ( my $cl = shift @queue ) {
+ push @path, $cl;
+ unshift @queue, grep { ! $seen{$_}++ }
+ map { s/^::/main::/; s/\'/::/g; $_ } ## no critic
+ map { "$_" }
+ ( @{"${cl}::ISA"} );
+ }
+
+ # Find and merge the function names across the entire super path.
+ # Sort alphabetically and return.
+ my %methods = ();
+ foreach my $namespace ( @path ) {
+ my @functions = grep { ! $methods{$_} }
+ grep { /$RE_IDENTIFIER/o }
+ grep { defined &{"${namespace}::$_"} }
+ keys %{"${namespace}::"};
+ foreach ( @functions ) {
+ $methods{$_} = $namespace;
+ }
+ }
+
+ # Filter to public or private methods if needed
+ my @methodlist = sort keys %methods;
+ @methodlist = grep { ! /^\_/ } @methodlist if $options{public};
+ @methodlist = grep { /^\_/ } @methodlist if $options{private};
+
+ # Return in the correct format
+ @methodlist = map { "$methods{$_}::$_" } @methodlist if $options{full};
+ @methodlist = map {
+ [ "$methods{$_}::$_", $methods{$_}, $_, \&{"$methods{$_}::$_"} ]
+ } @methodlist if $options{expanded};
+
+ \@methodlist;
+}
+
+
+
+
+
+#####################################################################
+# Search Methods
+
+
+sub subclasses {
+ my $class = shift;
+ my $name = $class->_class( shift ) or return undef;
+
+ # Prepare the search queue
+ my @found = ();
+ my @queue = grep { $_ ne 'main' } $class->_subnames('');
+ while ( @queue ) {
+ my $c = shift(@queue); # c for class
+ if ( $class->_loaded($c) ) {
+ # At least one person has managed to misengineer
+ # a situation in which ->isa could die, even if the
+ # class is real. Trap these cases and just skip
+ # over that (bizarre) class. That would at limit
+ # problems with finding subclasses to only the
+ # modules that have broken ->isa implementation.
+ local $@;
+ eval {
+ if ( $c->isa($name) ) {
+ # Add to the found list, but don't add the class itself
+ push @found, $c unless $c eq $name;
+ }
+ };
+ }
+
+ # Add any child namespaces to the head of the queue.
+ # This keeps the queue length shorted, and allows us
+ # not to have to do another sort at the end.
+ unshift @queue, map { "${c}::$_" } $class->_subnames($c);
+ }
+
+ @found ? \@found : '';
+}
+
+sub _subnames {
+ my ($class, $name) = @_;
+ return sort
+ grep { ## no critic
+ substr($_, -2, 2, '') eq '::'
+ and
+ /$RE_IDENTIFIER/o
+ }
+ keys %{"${name}::"};
+}
+
+
+
+
+
+#####################################################################
+# Children Related Methods
+
+# These can go undocumented for now, until I decide if its best to
+# just search the children in namespace only, or if I should do it via
+# the file system.
+
+# Find all the loaded classes below us
+sub children {
+ my $class = shift;
+ my $name = $class->_class(shift) or return ();
+
+ # Find all the Foo:: elements in our symbol table
+ no strict 'refs';
+ map { "${name}::$_" } sort grep { s/::$// } keys %{"${name}::"}; ## no critic
+}
+
+# As above, but recursively
+sub recursive_children {
+ my $class = shift;
+ my $name = $class->_class(shift) or return ();
+ my @children = ( $name );
+
+ # Do the search using a nicer, more memory efficient
+ # variant of actual recursion.
+ my $i = 0;
+ no strict 'refs';
+ while ( my $namespace = $children[$i++] ) {
+ push @children, map { "${namespace}::$_" }
+ grep { ! /^::/ } # Ignore things like ::ISA::CACHE::
+ grep { s/::$// } ## no critic
+ keys %{"${namespace}::"};
+ }
+
+ sort @children;
+}
+
+
+
+
+
+#####################################################################
+# Private Methods
+
+# Checks and expands ( if needed ) a class name
+sub _class {
+ my $class = shift;
+ my $name = shift or return '';
+
+ # Handle main shorthand
+ return 'main' if $name eq '::';
+ $name =~ s/\A::/main::/;
+
+ # Check the class name is valid
+ $name =~ /$RE_CLASS/o ? $name : '';
+}
+
+# Create a INC-specific filename, which always uses '/'
+# regardless of platform.
+sub _inc_filename {
+ my $class = shift;
+ my $name = $class->_class(shift) or return undef;
+ join( '/', split /(?:\'|::)/, $name ) . '.pm';
+}
+
+# Convert INC-specific file name to local file name
+sub _inc_to_local {
+ # Shortcut in the Unix case
+ return $_[1] if $UNIX;
+
+ # On other places, we have to deal with an unusual path that might look
+ # like C:/foo/bar.pm which doesn't fit ANY normal pattern.
+ # Putting it through splitpath/dir and back again seems to normalise
+ # it to a reasonable amount.
+ my $class = shift;
+ my $inc_name = shift or return undef;
+ my ($vol, $dir, $file) = File::Spec->splitpath( $inc_name );
+ $dir = File::Spec->catdir( File::Spec->splitdir( $dir || "" ) );
+ File::Spec->catpath( $vol, $dir, $file || "" );
+}
+
+1;
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::Inspector - Get information about a class and its structure
+
+=head1 VERSION
+
+version 1.36
+
+=head1 SYNOPSIS
+
+ use Class::Inspector;
+
+ # Is a class installed and/or loaded
+ Class::Inspector->installed( 'Foo::Class' );
+ Class::Inspector->loaded( 'Foo::Class' );
+
+ # Filename related information
+ Class::Inspector->filename( 'Foo::Class' );
+ Class::Inspector->resolved_filename( 'Foo::Class' );
+
+ # Get subroutine related information
+ Class::Inspector->functions( 'Foo::Class' );
+ Class::Inspector->function_refs( 'Foo::Class' );
+ Class::Inspector->function_exists( 'Foo::Class', 'bar' );
+ Class::Inspector->methods( 'Foo::Class', 'full', 'public' );
+
+ # Find all loaded subclasses or something
+ Class::Inspector->subclasses( 'Foo::Class' );
+
+=head1 DESCRIPTION
+
+Class::Inspector allows you to get information about a loaded class. Most or
+all of this information can be found in other ways, but they aren't always
+very friendly, and usually involve a relatively high level of Perl wizardry,
+or strange and unusual looking code. Class::Inspector attempts to provide
+an easier, more friendly interface to this information.
+
+=head1 METHODS
+
+=head2 installed
+
+ my $bool = Class::Inspector->installed($class);
+
+The C<installed> static method tries to determine if a class is installed
+on the machine, or at least available to Perl. It does this by wrapping
+around C<resolved_filename>.
+
+Returns true if installed/available, false if the class is not installed,
+or C<undef> if the class name is invalid.
+
+=head2 loaded
+
+ my $bool = Class::Inspector->loaded($class);
+
+The C<loaded> static method tries to determine if a class is loaded by
+looking for symbol table entries.
+
+This method it uses to determine this will work even if the class does not
+have its own file, but is contained inside a single file with multiple
+classes in it. Even in the case of some sort of run-time loading class
+being used, these typically leave some trace in the symbol table, so an
+L<Autoload> or L<Class::Autouse>-based class should correctly appear
+loaded.
+
+Returns true if the class is loaded, false if not, or C<undef> if the
+class name is invalid.
+
+=head2 filename
+
+ my $filename = Class::Inspector->filename($class);
+
+For a given class, returns the base filename for the class. This will NOT
+be a fully resolved filename, just the part of the filename BELOW the
+C<@INC> entry.
+
+ print Class->filename( 'Foo::Bar' );
+ > Foo/Bar.pm
+
+This filename will be returned with the right separator for the local
+platform, and should work on all platforms.
+
+Returns the filename on success or C<undef> if the class name is invalid.
+
+=head2 resolved_filename
+
+ my $filename = Class::Inspector->resolved_filename($class);
+ my $filename = Class::Inspector->resolved_filename($class, @try_first);
+
+For a given class, the C<resolved_filename> static method returns the fully
+resolved filename for a class. That is, the file that the class would be
+loaded from.
+
+This is not necessarily the file that the class WAS loaded from, as the
+value returned is determined each time it runs, and the C<@INC> include
+path may change.
+
+To get the actual file for a loaded class, see the C<loaded_filename>
+method.
+
+Returns the filename for the class, or C<undef> if the class name is
+invalid.
+
+=head2 loaded_filename
+
+ my $filename = Class::Inspector->loaded_filename($class);
+
+For a given loaded class, the C<loaded_filename> static method determines
+(via the C<%INC> hash) the name of the file that it was originally loaded
+from.
+
+Returns a resolved file path, or false if the class did not have it's own
+file.
+
+=head2 functions
+
+ my $arrayref = Class::Inspector->functions($class);
+
+For a loaded class, the C<functions> static method returns a list of the
+names of all the functions in the classes immediate namespace.
+
+Note that this is not the METHODS of the class, just the functions.
+
+Returns a reference to an array of the function names on success, or C<undef>
+if the class name is invalid or the class is not loaded.
+
+=head2 function_refs
+
+ my $arrayref = Class::Inspector->function_refs($class);
+
+For a loaded class, the C<function_refs> static method returns references to
+all the functions in the classes immediate namespace.
+
+Note that this is not the METHODS of the class, just the functions.
+
+Returns a reference to an array of C<CODE> refs of the functions on
+success, or C<undef> if the class is not loaded.
+
+=head2 function_exists
+
+ my $bool = Class::Inspector->function_exists($class, $functon);
+
+Given a class and function name the C<function_exists> static method will
+check to see if the function exists in the class.
+
+Note that this is as a function, not as a method. To see if a method
+exists for a class, use the C<can> method for any class or object.
+
+Returns true if the function exists, false if not, or C<undef> if the
+class or function name are invalid, or the class is not loaded.
+
+=head2 methods
+
+ my $arrayref = Class::Inspector->methods($class, @options);
+
+For a given class name, the C<methods> static method will returns ALL
+the methods available to that class. This includes all methods available
+from every class up the class' C<@ISA> tree.
+
+Returns a reference to an array of the names of all the available methods
+on success, or C<undef> if the class name is invalid or the class is not
+loaded.
+
+A number of options are available to the C<methods> method that will alter
+the results returned. These should be listed after the class name, in any
+order.
+
+ # Only get public methods
+ my $method = Class::Inspector->methods( 'My::Class', 'public' );
+
+=over 4
+
+=item public
+
+The C<public> option will return only 'public' methods, as defined by the Perl
+convention of prepending an underscore to any 'private' methods. The C<public>
+option will effectively remove any methods that start with an underscore.
+
+=item private
+
+The C<private> options will return only 'private' methods, as defined by the
+Perl convention of prepending an underscore to an private methods. The
+C<private> option will effectively remove an method that do not start with an
+underscore.
+
+B<Note: The C<public> and C<private> options are mutually exclusive>
+
+=item full
+
+C<methods> normally returns just the method name. Supplying the C<full> option
+will cause the methods to be returned as the full names. That is, instead of
+returning C<[ 'method1', 'method2', 'method3' ]>, you would instead get
+C<[ 'Class::method1', 'AnotherClass::method2', 'Class::method3' ]>.
+
+=item expanded
+
+The C<expanded> option will cause a lot more information about method to be
+returned. Instead of just the method name, you will instead get an array
+reference containing the method name as a single combined name, a la C<full>,
+the separate class and method, and a CODE ref to the actual function ( if
+available ). Please note that the function reference is not guaranteed to
+be available. C<Class::Inspector> is intended at some later time, to work
+with modules that have some kind of common run-time loader in place ( e.g
+C<Autoloader> or C<Class::Autouse> for example.
+
+The response from C<methods( 'Class', 'expanded' )> would look something like
+the following.
+
+ [
+ [ 'Class::method1', 'Class', 'method1', \&Class::method1 ],
+ [ 'Another::method2', 'Another', 'method2', \&Another::method2 ],
+ [ 'Foo::bar', 'Foo', 'bar', \&Foo::bar ],
+ ]
+
+=back
+
+=head2 subclasses
+
+ my $arrayref = Class::Inspector->subclasses($class);
+
+The C<subclasses> static method will search then entire namespace (and thus
+B<all> currently loaded classes) to find all classes that are subclasses
+of the class provided as a the parameter.
+
+The actual test will be done by calling C<isa> on the class as a static
+method. (i.e. C<My::Class-E<gt>isa($class)>.
+
+Returns a reference to a list of the loaded classes that match the class
+provided, or false is none match, or C<undef> if the class name provided
+is invalid.
+
+=head1 SEE ALSO
+
+L<http://ali.as/>, L<Class::Handle>, L<Class::Inspector::Functions>
+
+=head1 AUTHOR
+
+Original author: Adam Kennedy E<lt>adamk@cpan.orgE<gt>
+
+Current maintainer: Graham Ollis E<lt>plicease@cpan.orgE<gt>
+
+Contributors:
+
+Tom Wyant
+
+Steffen Müller
+
+Kivanc Yazan (KYZN)
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2002-2019 by Adam Kennedy.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
--- /dev/null
+package Class::Inspector::Functions;
+
+use 5.006;
+use strict;
+use warnings;
+use Exporter ();
+use Class::Inspector ();
+use base qw( Exporter );
+
+# ABSTRACT: Get information about a class and its structure
+our $VERSION = '1.36'; # VERSION
+
+BEGIN {
+
+ our @EXPORT = qw(
+ installed
+ loaded
+
+ filename
+ functions
+ methods
+
+ subclasses
+ );
+
+ our @EXPORT_OK = qw(
+ resolved_filename
+ loaded_filename
+
+ function_refs
+ function_exists
+ );
+ #children
+ #recursive_children
+
+ our %EXPORT_TAGS = ( ALL => [ @EXPORT_OK, @EXPORT ] );
+
+ foreach my $meth (@EXPORT, @EXPORT_OK) {
+ my $sub = Class::Inspector->can($meth);
+ no strict 'refs';
+ *{$meth} = sub {&$sub('Class::Inspector', @_)};
+ }
+
+}
+
+1;
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+Class::Inspector::Functions - Get information about a class and its structure
+
+=head1 VERSION
+
+version 1.36
+
+=head1 SYNOPSIS
+
+ use Class::Inspector::Functions;
+ # Class::Inspector provides a non-polluting,
+ # method based interface!
+
+ # Is a class installed and/or loaded
+ installed( 'Foo::Class' );
+ loaded( 'Foo::Class' );
+
+ # Filename related information
+ filename( 'Foo::Class' );
+ resolved_filename( 'Foo::Class' );
+
+ # Get subroutine related information
+ functions( 'Foo::Class' );
+ function_refs( 'Foo::Class' );
+ function_exists( 'Foo::Class', 'bar' );
+ methods( 'Foo::Class', 'full', 'public' );
+
+ # Find all loaded subclasses or something
+ subclasses( 'Foo::Class' );
+
+=head1 DESCRIPTION
+
+Class::Inspector::Functions is a function based interface of
+L<Class::Inspector>. For a thorough documentation of the available
+functions, please check the manual for the main module.
+
+=head2 Exports
+
+The following functions are exported by default.
+
+ installed
+ loaded
+ filename
+ functions
+ methods
+ subclasses
+
+The following functions are exported only by request.
+
+ resolved_filename
+ loaded_filename
+ function_refs
+ function_exists
+
+All the functions may be imported using the C<:ALL> tag.
+
+=head1 SEE ALSO
+
+L<http://ali.as/>, L<Class::Handle>, L<Class::Inspector>
+
+=head1 AUTHOR
+
+Original author: Adam Kennedy E<lt>adamk@cpan.orgE<gt>
+
+Current maintainer: Graham Ollis E<lt>plicease@cpan.orgE<gt>
+
+Contributors:
+
+Tom Wyant
+
+Steffen Müller
+
+Kivanc Yazan (KYZN)
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2002-2019 by Adam Kennedy.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
--- /dev/null
+#!/bin/bash
+
+set -ex
+
+cip exec cpanm Devel::Hide
+cip sudo dzil-cpanm Dist::Zilla::Plugin::OurPkgVersion
+
+if [ ! -z "$PERL_CRITIC" ]; then
+ cip exec cpanm -n Perl::Critic Perl::Critic::Freenode https://dist.wdlabs.com/Test2-Tools-PerlCritic-0.01.tar.gz
+ cip exec cpanm -n Test::EOL Test::Pod Test::Pod::Coverage Test::Pod::Spelling::CommonMistakes Test::Strict Test::Version Test::Fixme \
+ Test::NoTabs YAML
+fi
--- /dev/null
+#!/bin/bash
+
+set -ex
+
+perl Makefile.PL
+make
+make test TEST_VERBOSE=1
+prove -lr xt
--- /dev/null
+severity = 1
+only = 1
+
+[Freenode::ArrayAssignAref]
+[Freenode::BarewordFilehandles]
+[Freenode::ConditionalDeclarations]
+[Freenode::ConditionalImplicitReturn]
+[Freenode::DeprecatedFeatures]
+[Freenode::DiscouragedModules]
+[Freenode::DollarAB]
+[Freenode::Each]
+[Freenode::EmptyReturn]
+[Freenode::IndirectObjectNotation]
+[Freenode::LexicalForeachIterator]
+[Freenode::LoopOnHash]
+[Freenode::ModPerl]
+[Freenode::OpenArgs]
+[Freenode::OverloadOptions]
+[Freenode::POSIXImports]
+[Freenode::PackageMatchesFilename]
+[Freenode::PreferredAlternatives]
+[Freenode::Prototypes]
+[Freenode::StrictWarnings]
+extra_importers = Test2::V0
+[Freenode::Threads]
+[Freenode::Wantarray]
+[Freenode::WarningsSwitch]
+[Freenode::WhileDiamondDefaultAssignment]
+
+[BuiltinFunctions::ProhibitBooleanGrep]
+[BuiltinFunctions::ProhibitStringyEval]
+[BuiltinFunctions::ProhibitStringySplit]
+[BuiltinFunctions::ProhibitVoidGrep]
+[BuiltinFunctions::ProhibitVoidMap]
+[ClassHierarchies::ProhibitExplicitISA]
+[ClassHierarchies::ProhibitOneArgBless]
+[CodeLayout::ProhibitHardTabs]
+allow_leading_tabs = 0
+[CodeLayout::ProhibitTrailingWhitespace]
+[CodeLayout::RequireConsistentNewlines]
+[ControlStructures::ProhibitLabelsWithSpecialBlockNames]
+[ControlStructures::ProhibitMutatingListFunctions]
+[ControlStructures::ProhibitUnreachableCode]
+[InputOutput::ProhibitBarewordFileHandles]
+[InputOutput::ProhibitJoinedReadline]
+[InputOutput::ProhibitTwoArgOpen]
+[Miscellanea::ProhibitFormats]
+[Miscellanea::ProhibitUselessNoCritic]
+[Modules::ProhibitConditionalUseStatements]
+;[Modules::RequireEndWithOne]
+[Modules::RequireNoMatchVarsWithUseEnglish]
+[Objects::ProhibitIndirectSyntax]
+[RegularExpressions::ProhibitUselessTopic]
+[Subroutines::ProhibitNestedSubs]
+[ValuesAndExpressions::ProhibitLeadingZeros]
+[ValuesAndExpressions::ProhibitMixedBooleanOperators]
+[ValuesAndExpressions::ProhibitSpecialLiteralHeredocTerminator]
+[ValuesAndExpressions::RequireUpperCaseHeredocTerminator]
+[Variables::ProhibitPerl4PackageNames]
+[Variables::ProhibitUnusedVariables]
--- /dev/null
+use strict;
+use warnings;
+use Config;
+use Test::More tests => 1;
+
+# This .t file is generated.
+# make changes instead to dist.ini
+
+my %modules;
+my $post_diag;
+
+$modules{$_} = $_ for qw(
+ ExtUtils::MakeMaker
+ File::Spec
+ Test::More
+);
+
+
+
+my @modules = sort keys %modules;
+
+sub spacer ()
+{
+ diag '';
+ diag '';
+ diag '';
+}
+
+pass 'okay';
+
+my $max = 1;
+$max = $_ > $max ? $_ : $max for map { length $_ } @modules;
+our $format = "%-${max}s %s";
+
+spacer;
+
+my @keys = sort grep /(MOJO|PERL|\A(LC|HARNESS)_|\A(SHELL|LANG)\Z)/i, keys %ENV;
+
+if(@keys > 0)
+{
+ diag "$_=$ENV{$_}" for @keys;
+
+ if($ENV{PERL5LIB})
+ {
+ spacer;
+ diag "PERL5LIB path";
+ diag $_ for split $Config{path_sep}, $ENV{PERL5LIB};
+
+ }
+ elsif($ENV{PERLLIB})
+ {
+ spacer;
+ diag "PERLLIB path";
+ diag $_ for split $Config{path_sep}, $ENV{PERLLIB};
+ }
+
+ spacer;
+}
+
+diag sprintf $format, 'perl ', $];
+
+foreach my $module (@modules)
+{
+ my $pm = "$module.pm";
+ $pm =~ s{::}{/}g;
+ if(eval { require $pm; 1 })
+ {
+ my $ver = eval { $module->VERSION };
+ $ver = 'undef' unless defined $ver;
+ diag sprintf $format, $module, $ver;
+ }
+ else
+ {
+ diag sprintf $format, $module, '-';
+ }
+}
+
+if($post_diag)
+{
+ spacer;
+ $post_diag->();
+}
+
+spacer;
+
--- /dev/null
+use strict;
+use warnings;
+use Test::More tests => 3;
+
+ok( $] >= 5.006, "Your perl is new enough" );
+
+use_ok('Class::Inspector');
+use_ok('Class::Inspector::Functions');
--- /dev/null
+# Unit testing for Class::Inspector
+
+# Do all the tests on ourself, where possible, as we know we will be loaded.
+
+use strict;
+use warnings;
+use Test::More tests => 56;
+use Class::Inspector ();
+
+# To make maintaining this a little faster,
+# CI is defined as Class::Inspector, and
+# BAD for a class we know doesn't exist.
+use constant CI => 'Class::Inspector';
+use constant BAD => 'Class::Inspector::Nonexistant';
+
+# How many functions and public methods are there in Class::Inspector
+my $base_functions = 18;
+my $base_public = 12;
+my $base_private = $base_functions - $base_public;
+
+
+
+
+
+#####################################################################
+# Begin Tests
+
+# Check the good/bad class code
+ok( CI->_class( CI ), 'Class validator works for known valid' );
+ok( CI->_class( BAD ), 'Class validator works for correctly formatted, but not installed' );
+ok( CI->_class( 'A::B::C::D::E' ), 'Class validator works for long classes' );
+ok( CI->_class( '::' ), 'Class validator allows main' );
+ok( CI->_class( '::Blah' ), 'Class validator works for main aliased' );
+ok( ! CI->_class(), 'Class validator failed for missing class' );
+ok( ! CI->_class( '4teen' ), 'Class validator fails for number starting class' );
+ok( ! CI->_class( 'Blah::%f' ), 'Class validator catches bad characters' );
+
+
+
+
+
+
+# Check the loaded method
+ok( CI->loaded( CI ), "->loaded detects loaded" );
+ok( ! CI->loaded( BAD ), "->loaded detects not loaded" );
+
+
+
+
+
+# Check the file name methods
+my $filename = CI->filename( CI );
+ok( $filename eq File::Spec->catfile( "Class", "Inspector.pm" ), "->filename works correctly" );
+my $inc_filename = CI->_inc_filename( CI );
+ok( $inc_filename eq "Class/Inspector.pm", "->_inc_filename works correctly" );
+ok( index( CI->loaded_filename(CI), $filename ) >= 0, "->loaded_filename works" );
+ok( ($filename eq $inc_filename or index( CI->loaded_filename(CI), $inc_filename ) == -1), "->loaded_filename works" );
+ok( index( CI->resolved_filename(CI), $filename ) >= 0, "->resolved_filename works" );
+ok( ($filename eq $inc_filename or index( CI->resolved_filename(CI), $inc_filename ) == -1), "->resolved_filename works" );
+
+
+
+
+
+# Check the installed stuff
+ok( CI->installed( CI ), "->installed detects installed" );
+ok( ! CI->installed( BAD ), "->installed detects not installed" )
+ || do {
+ diag "\@INC=$_" for @INC;
+ diag "$_=$INC{$_}" for sort keys %INC;
+ };
+
+
+
+
+
+# Check the functions
+my $functions = CI->functions( CI );
+ok( (ref($functions) eq 'ARRAY'
+ and $functions->[0] eq '_class'
+ and scalar @$functions == $base_functions),
+ "->functions works correctly" );
+ok( ! CI->functions( BAD ), "->functions fails correctly" );
+
+
+
+
+
+# Check function refs
+$functions = CI->function_refs( CI );
+ok( (ref($functions) eq 'ARRAY'
+ and ref $functions->[0]
+ and ref($functions->[0]) eq 'CODE'
+ and scalar @$functions == $base_functions),
+ "->function_refs works correctly" );
+ok( ! CI->functions( BAD ), "->function_refs fails correctly" );
+
+
+
+
+
+# Check function_exists
+ok( CI->function_exists( CI, 'installed' ),
+ "->function_exists detects function that exists" );
+ok( ! CI->function_exists( CI, 'nsfladf' ),
+ "->function_exists fails for bad function" );
+ok( ! CI->function_exists( CI ),
+ "->function_exists fails for missing function" );
+ok( ! CI->function_exists( BAD, 'function' ),
+ "->function_exists fails for bad class" );
+
+
+
+
+
+# Check the methods method.
+# First, defined a new subclass of Class::Inspector with some additional methods
+CLASS: {
+ package Class::Inspector::Dummy;
+
+ use strict;
+ BEGIN {
+ require Class::Inspector;
+ @Class::Inspector::Dummy::ISA = 'Class::Inspector';
+ }
+
+ sub _a_first { 1; }
+ sub adummy1 { 1; }
+ sub _dummy2 { 1; }
+ sub dummy3 { 1; }
+ sub installed { 1; }
+}
+
+package main;
+
+my $methods = CI->methods( CI );
+ok( ( ref($methods) eq 'ARRAY'
+ and $methods->[0] eq '_class'
+ and scalar @$methods == $base_functions),
+ "->methods works for non-inheriting class" );
+$methods = CI->methods( 'Class::Inspector::Dummy' );
+ok( (ref($methods) eq 'ARRAY'
+ and $methods->[0] eq '_a_first'
+ and scalar @$methods == ($base_functions + 4)
+ and scalar( grep { /dummy/ } @$methods ) == 3),
+ "->methods works for inheriting class" );
+ok( ! CI->methods( BAD ), "->methods fails correctly" );
+
+# Check the variety of different possible ->methods options
+
+# Public option
+$methods = CI->methods( CI, 'public' );
+ok( (ref($methods) eq 'ARRAY'
+ and $methods->[0] eq 'children'
+ and scalar @$methods == $base_public),
+ "Public ->methods works for non-inheriting class" );
+$methods = CI->methods( 'Class::Inspector::Dummy', 'public' );
+ok( (ref($methods) eq 'ARRAY'
+ and $methods->[0] eq 'adummy1'
+ and scalar @$methods == ($base_public + 2)
+ and scalar( grep { /dummy/ } @$methods ) == 2),
+ "Public ->methods works for inheriting class" );
+ok( ! CI->methods( BAD ), "Public ->methods fails correctly" );
+
+# Private option
+$methods = CI->methods( CI, 'private' );
+ok( (ref($methods) eq 'ARRAY'
+ and $methods->[0] eq '_class'
+ and scalar @$methods == $base_private),
+ "Private ->methods works for non-inheriting class" );
+$methods = CI->methods( 'Class::Inspector::Dummy', 'private' );
+ok( (ref($methods) eq 'ARRAY'
+ and $methods->[0] eq '_a_first'
+ and scalar @$methods == ($base_private + 2)
+ and scalar( grep { /dummy/ } @$methods ) == 1),
+ "Private ->methods works for inheriting class" );
+ok( ! CI->methods( BAD ), "Private ->methods fails correctly" );
+
+# Full option
+$methods = CI->methods( CI, 'full' );
+ok( (ref($methods) eq 'ARRAY'
+ and $methods->[0] eq 'Class::Inspector::_class'
+ and scalar @$methods == $base_functions),
+ "Full ->methods works for non-inheriting class" );
+$methods = CI->methods( 'Class::Inspector::Dummy', 'full' );
+ok( (ref($methods) eq 'ARRAY'
+ and $methods->[0] eq 'Class::Inspector::Dummy::_a_first'
+ and scalar @$methods == ($base_functions + 4)
+ and scalar( grep { /dummy/ } @$methods ) == 3),
+ "Full ->methods works for inheriting class" );
+ok( ! CI->methods( BAD ), "Full ->methods fails correctly" );
+
+# Expanded option
+$methods = CI->methods( CI, 'expanded' );
+ok( (ref($methods) eq 'ARRAY'
+ and ref($methods->[0]) eq 'ARRAY'
+ and $methods->[0]->[0] eq 'Class::Inspector::_class'
+ and $methods->[0]->[1] eq 'Class::Inspector'
+ and $methods->[0]->[2] eq '_class'
+ and ref($methods->[0]->[3]) eq 'CODE'
+ and scalar @$methods == $base_functions),
+ "Expanded ->methods works for non-inheriting class" );
+$methods = CI->methods( 'Class::Inspector::Dummy', 'expanded' );
+ok( (ref($methods) eq 'ARRAY'
+ and ref($methods->[0]) eq 'ARRAY'
+ and $methods->[0]->[0] eq 'Class::Inspector::Dummy::_a_first'
+ and $methods->[0]->[1] eq 'Class::Inspector::Dummy'
+ and $methods->[0]->[2] eq '_a_first'
+ and ref($methods->[0]->[3]) eq 'CODE'
+ and scalar @$methods == ($base_functions + 4)
+ and scalar( grep { /dummy/ } map { $_->[2] } @$methods ) == 3),
+ "Expanded ->methods works for inheriting class" );
+ok( ! CI->methods( BAD ), "Expanded ->methods fails correctly" );
+
+# Check clashing between options
+ok( ! CI->methods( CI, 'public', 'private' ), "Public and private ->methods clash correctly" );
+ok( ! CI->methods( CI, 'private', 'public' ), "Public and private ->methods clash correctly" );
+ok( ! CI->methods( CI, 'full', 'expanded' ), "Full and expanded ->methods class correctly" );
+ok( ! CI->methods( CI, 'expanded', 'full' ), "Full and expanded ->methods class correctly" );
+
+# Check combining options
+$methods = CI->methods( CI, 'public', 'expanded' );
+ok( (ref($methods) eq 'ARRAY'
+ and ref($methods->[0]) eq 'ARRAY'
+ and $methods->[0]->[0] eq 'Class::Inspector::children'
+ and $methods->[0]->[1] eq 'Class::Inspector'
+ and $methods->[0]->[2] eq 'children'
+ and ref($methods->[0]->[3]) eq 'CODE'
+ and scalar @$methods == $base_public),
+ "Public + Expanded ->methods works for non-inheriting class" );
+$methods = CI->methods( 'Class::Inspector::Dummy', 'public', 'expanded' );
+ok( (ref($methods) eq 'ARRAY'
+ and ref($methods->[0]) eq 'ARRAY'
+ and $methods->[0]->[0] eq 'Class::Inspector::Dummy::adummy1'
+ and $methods->[0]->[1] eq 'Class::Inspector::Dummy'
+ and $methods->[0]->[2] eq 'adummy1'
+ and ref($methods->[0]->[3]) eq 'CODE'
+ and scalar @$methods == ($base_public + 2)
+ and scalar( grep { /dummy/ } map { $_->[2] } @$methods ) == 2),
+ "Public + Expanded ->methods works for inheriting class" );
+ok( ! CI->methods( BAD ), "Expanded ->methods fails correctly" );
+
+
+
+
+
+#####################################################################
+# Search Tests
+
+# Create the classes to use
+CLASSES: {
+ package Foo;
+
+ sub foo { 1 };
+
+ package Foo::Subclass;
+
+ @Foo::Subclass::ISA = 'Foo';
+
+ package Bar;
+
+ @Bar::ISA = 'Foo';
+
+ package This;
+
+ sub isa { $_[1] eq 'Foo' ? 1 : undef }
+
+ 1;
+}
+
+# Check trivial ->find cases
+SCOPE: {
+ is( CI->subclasses( '' ), undef, '->subclasses(bad) returns undef' );
+ is( CI->subclasses( BAD ), '', '->subclasses(none) returns false' );
+ my $rv = CI->subclasses( CI );
+ is_deeply( $rv, [ 'Class::Inspector::Dummy' ], '->subclasses(CI) returns just itself' );
+
+ # Check non-trivial ->subclasses cases
+ $rv = CI->subclasses( 'Foo' );
+ is_deeply( $rv, [ 'Bar', 'Foo::Subclass', 'This' ],
+ '->subclasses(nontrivial) returns the expected class list' );
+}
+
+
+
+
+
+#####################################################################
+# Regression Tests
+
+# Discovered in 1.06, fixed in 1.07
+# In some cases, spurious empty GLOB entries can be created in a package.
+# These contain no actual symbols, but were causing ->loaded to return true.
+# An empty namespace with a single spurious empty glob entry (although
+# created in this test with a scalar) should return FALSE for ->loaded
+$Class::Inspector::SpuriousPackage::something = 1;
+$Class::Inspector::SpuriousPackage::something = 1; # Avoid a warning
+ok( ! Class::Inspector->loaded('Class::Inspector::SpuriousPackage'),
+ '->loaded returns false for spurious glob in package' );
+
+
+
+# Discovered in 1.11, fixed in 1.12
+# With the introduction of ->subclasses, we exposed ourselves to
+# non-local problems with ->isa method implementations.
+PACKAGES: {
+ # The busted package
+ package Class::Inspector::BrokenISA;
+ use vars qw{&isa};
+ our $VERSION = '0.01';
+ # The test packages
+ package My::Foo;
+ our $VERSION = '0.01';
+ package My::Bar;
+ our $VERSION = '0.01';
+ use base qw( My::Foo );
+}
+TESTS: {
+ my $rv = Class::Inspector->subclasses( 'My::Foo' );
+ is_deeply( $rv, [ 'My::Bar' ],
+ '->subclasses in the presence of an evil ->isa does not crash' );
+}
+
+
+{
+ {
+ package Baz;
+
+ our @ISA = qw( ::foo bar'baz ); ## no critic
+ }
+
+ is_deeply \@Baz::ISA, [qw( ::foo bar'baz )];
+
+ Class::Inspector->methods('Baz');
+
+ is_deeply \@Baz::ISA, [qw( ::foo bar'baz )];
+}
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+use Class::Inspector;
+
+eval { require Devel::Hide };
+plan skip_all => 'test requires Devel::Hide' if $@;
+plan tests => 2;
+
+ok( Class::Inspector->installed('Class::Inspector') );
+ok( ! Class::Inspector->installed('Class::Inspector::Bogus') );
--- /dev/null
+# Unit testing for Class::Inspector
+
+# Do all the tests on ourself, where possible, as we know we will be loaded.
+
+use strict;
+use warnings;
+use Test::More tests => 2;
+use Class::Inspector ();
+
+
+
+
+#####################################################################
+# Try the simplistic Win32 approach
+
+SKIP: {
+ skip( "Skipping Win32 test", 1 ) unless $^O eq 'MSWin32';
+ my $inc = 'C:/foo/bar.pm';
+ my $local = Class::Inspector->_inc_to_local($inc);
+ is( $local, 'C:\foo\bar.pm', '->_inc_to_local ok' );
+}
+
+
+
+
+
+#####################################################################
+# More general tests
+
+my $module = Class::Inspector->_inc_to_local($INC{'Class/Inspector.pm'});
+ok( -f $module, 'Found ourself' );
--- /dev/null
+# Reproduce some of the unit tests in the main unit tests
+# of the method interface, but not all. This makes the maintenance
+# slightly less annoying.
+
+use strict;
+use warnings;
+use Test::More tests => 24;
+use Class::Inspector::Functions;
+
+# To make maintaining this a little faster,
+# CI is defined as Class::Inspector, and
+# BAD for a class we know doesn't exist.
+use constant CI => 'Class::Inspector';
+use constant BAD => 'Class::Inspector::Nonexistant';
+
+my @exported_functions = qw(
+ installed
+ loaded
+ filename
+ functions
+ methods
+ subclasses
+);
+
+my @exportok_functions = qw(
+ loaded_filename
+ function_refs
+ function_exists
+);
+
+#####################################################################
+# Begin Tests
+
+# check the export lists:
+foreach my $function (@exported_functions) {
+ ok( main->can($function), "exported function '$function' was found" );
+}
+
+foreach my $function (@exportok_functions) {
+ ok( ! main->can($function), "optionally exported function '$function' was not found" );
+}
+
+Class::Inspector::Functions->import(':ALL');
+
+foreach my $function (@exportok_functions) {
+ ok( main->can($function), "optionally exported function '$function' was found after full import" );
+}
+
+
+
+# Check the loaded function
+ok( loaded( CI ), "loaded detects loaded" );
+ok( ! loaded( BAD ), "loaded detects not loaded" );
+
+# Check the file name functions
+my $filename = filename( CI );
+ok( $filename eq File::Spec->catfile( "Class", "Inspector.pm" ), "filename works correctly" );
+ok( index( loaded_filename(CI), $filename ) >= 0, "loaded_filename works" );
+my $inc_filename = CI->_inc_filename( CI );
+ok( ($filename eq $inc_filename or index( loaded_filename(CI), $inc_filename ) == -1), "loaded_filename works" );
+ok( index( resolved_filename(CI), $filename ) >= 0, "resolved_filename works" );
+ok( ($filename eq $inc_filename or index( resolved_filename(CI), $inc_filename ) == -1), "resolved_filename works" );
+
+unshift @INC, sub {
+ my $coderef = shift;
+ my $filename = shift;
+
+ if ($filename eq 'Foo/Bar.pm') {
+ open my $fh, '<', __FILE__;
+ return (undef, $fh);
+ }
+ return
+};
+
+unshift @INC, [ sub {
+ my $arrayref = shift;
+ my $filename = shift;
+
+ die "args wrong" unless
+ ref($arrayref->[0]) eq 'CODE'
+ && $arrayref->[1] == 1
+ && $arrayref->[2] == 2
+ && $arrayref->[3] == 3;
+
+ if($filename eq 'Foo/Baz.pm') {
+ open my $fh, '<', __FILE__;
+ return $fh;
+ }
+ return
+}, 1,2,3];
+
+unshift @INC, MyHook->new;
+
+# Check the installed stuff
+ok( installed( CI ), "installed detects installed" );
+ok( ! installed( BAD ), "installed detects not installed" );
+ok( installed( 'Foo::Bar'), "installed detects coderef installed" );
+ok( installed( 'Foo::Baz'), "installed detects arrayref installed" );
+ok( installed( 'Foo::Foo'), "installed detects object installed" );
+
+package
+ MyHook;
+
+sub new {
+ my($class) = @_;
+ bless {}, $class;
+}
+
+sub MyHook::INC {
+ my($self, $filename) = @_;
+ die "self wrong" unless ref $self eq 'MyHook';
+
+ if($filename eq 'Foo/Foo.pm') {
+ open my $fh, '<', __FILE__;
+ return $fh;
+ }
+ return ();
+}
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+
+BEGIN {
+ if(eval { require Test2::Tools::PerlCritic; 1 })
+ {
+ Test2::Tools::PerlCritic->import;
+ }
+ else
+ {
+ plan skip_all => 'Test requires Test2::Tools::PerlCritic';
+ }
+}
+
+my $critic = Perl::Critic->new(
+ -profile => 'perlcriticrc',
+);
+
+perl_critic_ok ['lib','t'], $critic;
+
+done_testing;
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+BEGIN {
+ plan skip_all => 'test requires Test::EOL'
+ unless eval q{ use Test::EOL; 1 };
+};
+use Test::EOL;
+use FindBin;
+use File::Spec;
+
+chdir(File::Spec->catdir($FindBin::Bin, File::Spec->updir, File::Spec->updir));
+
+all_perl_files_ok(grep { -e $_ } qw( bin lib t Makefile.PL ));
+
+
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+BEGIN {
+ plan skip_all => 'test requires Test::NoTabs'
+ unless eval q{ use Test::NoTabs; 1 };
+};
+use Test::NoTabs;
+use FindBin;
+use File::Spec;
+
+chdir(File::Spec->catdir($FindBin::Bin, File::Spec->updir, File::Spec->updir));
+
+all_perl_files_ok( grep { -e $_ } qw( bin lib t Makefile.PL ));
+
+
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+BEGIN {
+ plan skip_all => 'test requires Test::Pod'
+ unless eval q{ use Test::Pod; 1 };
+};
+use Test::Pod;
+use FindBin;
+use File::Spec;
+
+chdir(File::Spec->catdir($FindBin::Bin, File::Spec->updir, File::Spec->updir));
+
+all_pod_files_ok( grep { -e $_ } qw( bin lib ));
+
+
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+BEGIN {
+ plan skip_all => 'test requires 5.010 or better'
+ unless $] >= 5.010;
+ plan skip_all => 'test requires Test::Pod::Coverage'
+ unless eval q{ use Test::Pod::Coverage; 1 };
+ plan skip_all => 'test requires YAML'
+ unless eval q{ use YAML; 1; };
+};
+use Test::Pod::Coverage;
+use YAML qw( LoadFile );
+use FindBin;
+use File::Spec;
+
+my $config_filename = File::Spec->catfile(
+ $FindBin::Bin, File::Spec->updir, File::Spec->updir, 'author.yml'
+);
+
+my $config;
+$config = LoadFile($config_filename)
+ if -r $config_filename;
+
+plan skip_all => 'disabled' if $config->{pod_coverage}->{skip};
+
+chdir(File::Spec->catdir($FindBin::Bin, File::Spec->updir, File::Spec->updir));
+
+my @private_classes;
+my %private_methods;
+
+push @{ $config->{pod_coverage}->{private} },
+ 'Alien::.*::Install::Files#Inline';
+
+foreach my $private (@{ $config->{pod_coverage}->{private} })
+{
+ my($class,$method) = split /#/, $private;
+ if(defined $class && $class ne '')
+ {
+ my $regex = eval 'qr{^' . $class . '$}';
+ if(defined $method && $method ne '')
+ {
+ push @private_classes, { regex => $regex, method => $method };
+ }
+ else
+ {
+ push @private_classes, { regex => $regex, all => 1 };
+ }
+ }
+ elsif(defined $method && $method ne '')
+ {
+ $private_methods{$_} = 1 for split /,/, $method;
+ }
+}
+
+my @classes = all_modules;
+
+plan tests => scalar @classes;
+
+foreach my $class (@classes)
+{
+ SKIP: {
+ my($is_private_class) = map { 1 } grep { $class =~ $_->{regex} && $_->{all} } @private_classes;
+ skip "private class: $class", 1 if $is_private_class;
+
+ my %methods = map {; $_ => 1 } map { split /,/, $_->{method} } grep { $class =~ $_->{regex} } @private_classes;
+ $methods{$_} = 1 for keys %private_methods;
+
+ my $also_private = eval 'qr{^' . join('|', keys %methods ) . '$}';
+
+ pod_coverage_ok $class, { also_private => [$also_private] };
+ };
+}
+
+
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+BEGIN {
+ plan skip_all => 'test requires Test::Pod::Spelling::CommonMistakes'
+ unless eval q{ use Test::Pod::Spelling::CommonMistakes; 1 };
+ plan skip_all => 'test requires YAML'
+ unless eval q{ use YAML qw( LoadFile ); 1 };
+};
+use Test::Pod::Spelling::CommonMistakes;
+use FindBin;
+use File::Spec;
+
+my $config_filename = File::Spec->catfile(
+ $FindBin::Bin, File::Spec->updir, File::Spec->updir, 'author.yml'
+);
+
+my $config;
+$config = LoadFile($config_filename)
+ if -r $config_filename;
+
+plan skip_all => 'disabled' if $config->{pod_spelling_common}->{skip};
+
+chdir(File::Spec->catdir($FindBin::Bin, File::Spec->updir, File::Spec->updir));
+
+# TODO: test files in bin too.
+all_pod_files_ok;
+
+
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+BEGIN {
+ plan skip_all => 'test requires Test::Strict'
+ unless eval q{ use Test::Strict; 1 };
+};
+use Test::Strict;
+use FindBin;
+use File::Spec;
+
+chdir(File::Spec->catdir($FindBin::Bin, File::Spec->updir, File::Spec->updir));
+
+unshift @Test::Strict::MODULES_ENABLING_STRICT,
+ 'ozo',
+ 'Test2::Bundle::SIPS',
+ 'Test2::V0',
+ 'Test2::Bundle::Extended';
+note "enabling strict = $_" for @Test::Strict::MODULES_ENABLING_STRICT;
+
+all_perl_files_ok( grep { -e $_ } qw( bin lib t Makefile.PL ));
+
+
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+use FindBin ();
+BEGIN {
+
+ plan skip_all => "test requires Test::Version 2.00"
+ unless eval q{
+ use Test::Version 2.00 qw( version_all_ok ), {
+ has_version => 1,
+ filename_match => sub { $_[0] !~ m{/(ConfigData|Install/Files)\.pm$} },
+ };
+ 1
+ };
+
+ plan skip_all => 'test requires YAML'
+ unless eval q{ use YAML; 1; };
+}
+
+use YAML qw( LoadFile );
+use FindBin;
+use File::Spec;
+
+my $config_filename = File::Spec->catfile(
+ $FindBin::Bin, File::Spec->updir, File::Spec->updir, 'author.yml'
+);
+
+my $config;
+$config = LoadFile($config_filename)
+ if -r $config_filename;
+
+if($config->{version}->{dir})
+{
+ note "using dir " . $config->{version}->{dir}
+}
+
+version_all_ok($config->{version}->{dir} ? ($config->{version}->{dir}) : ());
+done_testing;
+
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+BEGIN {
+ plan skip_all => 'test requires Test::Fixme'
+ unless eval q{ use Test::Fixme 0.14; 1 };
+};
+use Test::Fixme 0.07;
+use FindBin;
+use File::Spec;
+
+chdir(File::Spec->catdir($FindBin::Bin, File::Spec->updir, File::Spec->updir));
+
+run_tests(
+ match => qr/FIXME/,
+ where => [ grep { -e $_ } qw( bin lib t Makefile.PL Build.PL )],
+ warn => 1,
+);
+
+