11 use vars qw( $VERSION $PERL $UNTAINT_PATTERN $PERL_PATTERN);
15 $PERL = $^X || 'perl';
16 $UNTAINT_PATTERN = qr|^([-+@\w./:\\]+)$|;
17 $PERL_PATTERN = qr/^#!.*perl/;
19 my %file_find_arg = ($] <= 5.006) ? () : (
21 untaint_pattern => $UNTAINT_PATTERN,
25 my $Test = Test::Builder->new;
26 my $updir = File::Spec->updir();
33 *{$caller.'::notabs_ok'} = \¬abs_ok;
34 *{$caller.'::all_perl_files_ok'} = \&all_perl_files_ok;
36 $Test->exported_to($caller);
41 my @all_files = _all_files(@_);
42 return grep { _is_perl_module($_) || _is_perl_script($_) } @all_files;
46 my @base_dirs = @_ ? @_ : File::Spec->catdir($Bin, $updir);
49 return if ($File::Find::dir =~ m![\\/]?CVS[\\/]|[\\/]?.svn[\\/]!); # Filter out cvs or subversion dirs/
50 return if ($File::Find::dir =~ m![\\/]?blib[\\/]libdoc$!); # Filter out pod doc in dist
51 return if ($File::Find::dir =~ m![\\/]?blib[\\/]man\d$!); # Filter out pod doc in dist
52 return if ($File::Find::name =~ m!Build$!i); # Filter out autogenerated Build script
53 return unless (-f $File::Find::name && -r _);
54 push @found, File::Spec->no_upwards( $File::Find::name );
61 find( $find_arg, @base_dirs);
67 my $test_txt = shift || "Found tabs in '$file'";
68 $file = _module_to_path($file);
69 open my $fh, $file or do { $Test->ok(0, $test_txt); $Test->diag("Could not open $file: $!"); return; };
74 next if (/^\s*=.+/ .. /^\s*=(cut|back|end)/);
75 last if (/^\s*(__END__|__DATA__)/);
77 $Test->ok(0, $test_txt . " on line $line");
81 $Test->ok(1, $test_txt);
85 sub all_perl_files_ok {
86 my @files = _all_perl_files( @_ );
88 foreach my $file ( @files ) {
94 $_[0] =~ /\.pm$/i || $_[0] =~ /::/;
99 return 1 if $file =~ /\.pl$/i;
100 return 1 if $file =~ /\.t$/;
101 open my $fh, $file or return;
103 return 1 if defined $first && ($first =~ $PERL_PATTERN);
107 sub _module_to_path {
109 return $file unless ($file =~ /::/);
110 my @parts = split /::/, $file;
111 my $module = File::Spec->catfile(@parts) . '.pm';
112 foreach my $dir (@INC) {
113 my $candidate = File::Spec->catfile($dir, $module);
114 next unless (-e $candidate && -f _ && -r _);
121 unless ($Test->has_plan) {
122 $Test->plan( 'no_plan' );
124 $Test->expected_tests;
128 my @untainted = map { ($_ =~ $UNTAINT_PATTERN) } @_;
129 return wantarray ? @untainted : $untainted[0];
137 Test::NoTabs - Check the presence of tabs in your project
141 C<Test::NoTabs> lets you check the presence of tabs in your perl code. It
142 report its results in standard C<Test::Simple> fashion:
144 use Test::NoTabs tests => 1;
145 notabs_ok( 'lib/Module.pm', 'Module is tab free');
147 Module authors can include the following in a t/notabs.t and have C<Test::NoTabs>
148 automatically find and check all perl files in a module distribution:
156 all_perl_files_ok( @mydirs );
160 This module scans your project/distribution for any perl files (scripts,
161 modules, etc) for the presence of tabs.
165 A list of functions that can be exported. You can delete this section
166 if you don't export anything, such as for a purely object-oriented module.
170 =head2 all_perl_files_ok( [ @directories ] )
172 Applies C<notabs_ok()> to all perl files found in C<@directories> (and sub
173 directories). If no <@directories> is given, the starting point is one level
174 above the current running script, that should cover all the files of a typical
175 CPAN distribution. A perl file is *.pl or *.pm or *.t or a file starting
178 If the test plan is defined:
180 use Test::NoTabs tests => 3;
183 the total number of files tested must be specified.
185 =head2 notabs_ok( $file [, $text] )
187 Run a tab check on C<$file>. For a module, the path (lib/My/Module.pm) or the
188 name (My::Module) can be both used.
192 Nick Gerakines, C<< <nick at socklabs.com> >>
196 Please report any bugs or feature requests to
197 C<bug-test-notabs at rt.cpan.org>, or through the web interface at
198 L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Test-NoTabs>.
199 I will be notified, and then you'll automatically be notified of progress on
200 your bug as I make changes.
204 You can find documentation for this module with the perldoc command.
208 You can also look for information at:
212 =item * AnnoCPAN: Annotated CPAN documentation
214 L<http://annocpan.org/dist/Test-NoTabs>
218 L<http://cpanratings.perl.org/d/Test-NoTabs>
220 =item * RT: CPAN's request tracker
222 L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Test-NoTabs>
226 L<http://search.cpan.org/dist/Test-NoTabs>
230 =head1 ACKNOWLEDGEMENTS
232 Inspired by some code written by Paul Lindner.
234 L<Test::Strict> was used as an example when creating this module and
237 Rick Myers and Emanuele Zeppieri also provided valuable feedback.
239 Patch to fix warnings provided by Florian Ragwitz
241 Currently maintained by Tomas Doran C<bobtfish@bobtfish.net>
245 L<Test::More>, L<Test::Pod>. L<Test::Distribution>, L<Test:NoWarnings>
247 =head1 COPYRIGHT & LICENSE
249 Copyright 2006 Nick Gerakines, all rights reserved.
251 This program is free software; you can redistribute it and/or modify it
252 under the same terms as Perl itself.