Imported Upstream version 1.36 upstream/1.36
authorTizenOpenSource <tizenopensrc@samsung.com>
Thu, 8 Feb 2024 09:32:25 +0000 (18:32 +0900)
committerTizenOpenSource <tizenopensrc@samsung.com>
Thu, 8 Feb 2024 09:32:25 +0000 (18:32 +0900)
30 files changed:
Changes [new file with mode: 0644]
INSTALL [new file with mode: 0644]
LICENSE [new file with mode: 0644]
MANIFEST [new file with mode: 0644]
META.json [new file with mode: 0644]
META.yml [new file with mode: 0644]
Makefile.PL [new file with mode: 0644]
README [new file with mode: 0644]
author.yml [new file with mode: 0644]
dist.ini [new file with mode: 0644]
lib/Class/Inspector.pm [new file with mode: 0644]
lib/Class/Inspector/Functions.pm [new file with mode: 0644]
maint/cip-before-install [new file with mode: 0755]
maint/cip-test [new file with mode: 0755]
perlcriticrc [new file with mode: 0644]
t/00_diag.t [new file with mode: 0644]
t/01_use.t [new file with mode: 0644]
t/class_inspector.t [new file with mode: 0644]
t/class_inspector__devel_hide.t [new file with mode: 0644]
t/class_inspector__inc_to_local.t [new file with mode: 0644]
t/class_inspector_functions.t [new file with mode: 0644]
xt/author/critic.t [new file with mode: 0644]
xt/author/eol.t [new file with mode: 0644]
xt/author/no_tabs.t [new file with mode: 0644]
xt/author/pod.t [new file with mode: 0644]
xt/author/pod_coverage.t [new file with mode: 0644]
xt/author/pod_spelling_common.t [new file with mode: 0644]
xt/author/strict.t [new file with mode: 0644]
xt/author/version.t [new file with mode: 0644]
xt/release/fixme.t [new file with mode: 0644]

diff --git a/Changes b/Changes
new file mode 100644 (file)
index 0000000..cef06bc
--- /dev/null
+++ b/Changes
@@ -0,0 +1,166 @@
+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
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..47a0a7d
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,72 @@
+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
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..d903374
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,379 @@
+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
+
diff --git a/MANIFEST b/MANIFEST
new file mode 100644 (file)
index 0000000..d5765bc
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,31 @@
+# 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
diff --git a/META.json b/META.json
new file mode 100644 (file)
index 0000000..570990a
--- /dev/null
+++ b/META.json
@@ -0,0 +1,87 @@
+{
+   "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
+}
+
diff --git a/META.yml b/META.yml
new file mode 100644 (file)
index 0000000..e783417
--- /dev/null
+++ b/META.yml
@@ -0,0 +1,43 @@
+---
+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
diff --git a/Makefile.PL b/Makefile.PL
new file mode 100644 (file)
index 0000000..39c1147
--- /dev/null
@@ -0,0 +1,67 @@
+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
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..c17315a
--- /dev/null
+++ b/README
@@ -0,0 +1,255 @@
+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.
+
diff --git a/author.yml b/author.yml
new file mode 100644 (file)
index 0000000..0e13d19
--- /dev/null
@@ -0,0 +1,15 @@
+---
+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
diff --git a/dist.ini b/dist.ini
new file mode 100644 (file)
index 0000000..1581a9c
--- /dev/null
+++ b/dist.ini
@@ -0,0 +1,61 @@
+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
diff --git a/lib/Class/Inspector.pm b/lib/Class/Inspector.pm
new file mode 100644 (file)
index 0000000..4911d12
--- /dev/null
@@ -0,0 +1,662 @@
+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
diff --git a/lib/Class/Inspector/Functions.pm b/lib/Class/Inspector/Functions.pm
new file mode 100644 (file)
index 0000000..b05b9bb
--- /dev/null
@@ -0,0 +1,136 @@
+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
diff --git a/maint/cip-before-install b/maint/cip-before-install
new file mode 100755 (executable)
index 0000000..c6a804d
--- /dev/null
@@ -0,0 +1,12 @@
+#!/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
diff --git a/maint/cip-test b/maint/cip-test
new file mode 100755 (executable)
index 0000000..82e851d
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+set -ex
+
+perl Makefile.PL
+make
+make test TEST_VERBOSE=1
+prove -lr xt
diff --git a/perlcriticrc b/perlcriticrc
new file mode 100644 (file)
index 0000000..5241092
--- /dev/null
@@ -0,0 +1,60 @@
+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]
diff --git a/t/00_diag.t b/t/00_diag.t
new file mode 100644 (file)
index 0000000..f1e814f
--- /dev/null
@@ -0,0 +1,85 @@
+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;
+
diff --git a/t/01_use.t b/t/01_use.t
new file mode 100644 (file)
index 0000000..f501820
--- /dev/null
@@ -0,0 +1,8 @@
+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');
diff --git a/t/class_inspector.t b/t/class_inspector.t
new file mode 100644 (file)
index 0000000..70375e8
--- /dev/null
@@ -0,0 +1,337 @@
+# 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 )];
+}
diff --git a/t/class_inspector__devel_hide.t b/t/class_inspector__devel_hide.t
new file mode 100644 (file)
index 0000000..9789709
--- /dev/null
@@ -0,0 +1,11 @@
+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') );
diff --git a/t/class_inspector__inc_to_local.t b/t/class_inspector__inc_to_local.t
new file mode 100644 (file)
index 0000000..f44c60e
--- /dev/null
@@ -0,0 +1,31 @@
+# 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' );
diff --git a/t/class_inspector_functions.t b/t/class_inspector_functions.t
new file mode 100644 (file)
index 0000000..3672085
--- /dev/null
@@ -0,0 +1,118 @@
+# 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 ();
+}
diff --git a/xt/author/critic.t b/xt/author/critic.t
new file mode 100644 (file)
index 0000000..7af1e67
--- /dev/null
@@ -0,0 +1,22 @@
+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;
diff --git a/xt/author/eol.t b/xt/author/eol.t
new file mode 100644 (file)
index 0000000..21395b5
--- /dev/null
@@ -0,0 +1,16 @@
+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 ));
+
+
diff --git a/xt/author/no_tabs.t b/xt/author/no_tabs.t
new file mode 100644 (file)
index 0000000..d62d42f
--- /dev/null
@@ -0,0 +1,16 @@
+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 ));
+
+
diff --git a/xt/author/pod.t b/xt/author/pod.t
new file mode 100644 (file)
index 0000000..282ed97
--- /dev/null
@@ -0,0 +1,16 @@
+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 ));
+
+
diff --git a/xt/author/pod_coverage.t b/xt/author/pod_coverage.t
new file mode 100644 (file)
index 0000000..bd70549
--- /dev/null
@@ -0,0 +1,75 @@
+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] };
+  };
+}
+
+
diff --git a/xt/author/pod_spelling_common.t b/xt/author/pod_spelling_common.t
new file mode 100644 (file)
index 0000000..75b9f8d
--- /dev/null
@@ -0,0 +1,29 @@
+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;
+
+
diff --git a/xt/author/strict.t b/xt/author/strict.t
new file mode 100644 (file)
index 0000000..37aea42
--- /dev/null
@@ -0,0 +1,23 @@
+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 ));
+
+
diff --git a/xt/author/version.t b/xt/author/version.t
new file mode 100644 (file)
index 0000000..153e334
--- /dev/null
@@ -0,0 +1,39 @@
+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;
+
diff --git a/xt/release/fixme.t b/xt/release/fixme.t
new file mode 100644 (file)
index 0000000..73bae2c
--- /dev/null
@@ -0,0 +1,20 @@
+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,
+);
+
+