#!/usr/bin/env perl use strict; use warnings; use YAML::Syck; use File::Find; use Getopt::Long; use lib qw( t/lib lib ); my $verbose = 0; GetOptions( "verbose" => \$verbose, ); our $config = {}; my $home = $ENV{HOME}; if (-f "$home/.a8rc") { $config = LoadFile("$home/.a8rc"); } my $fixture_base = $config->{fixture_base}; die "Must provide fixture_base in ~/.a8rc!\n" unless $fixture_base; my $fixture_base_path = $fixture_base; $fixture_base_path =~ s#::#/#g; my @INC_DIRECTORIES = grep { -d $_ } ($config->{fixture_root}, @INC); my %PROCESSED_PACKAGES = (); my @FILES = (); my %METHODS = (); my @PACKAGES = ($fixture_base); warn "Looking for packages in:\n" . join("\n", @INC_DIRECTORIES) . "\n" if ($verbose); my $want_child_classes = sub { my $filename = $File::Find::name; if ($filename =~ /\/$fixture_base_path\/.*\.pm$/) { my ($class_file) = $filename =~ /($fixture_base_path\/.*)\.pm$/; $class_file =~ s#/#::#g; return if (exists($PROCESSED_PACKAGES{$class_file}) or grep(/^$class_file$/, @PACKAGES)); push @PACKAGES, $class_file; } }; find($want_child_classes, @INC_DIRECTORIES); while (my $package = shift @PACKAGES) { next if (exists($PROCESSED_PACKAGES{$package})); my $package_file = join("/", split(/::/, $package)) . ".pm"; DIR: foreach my $directory (@INC_DIRECTORIES) { my $filename = "$directory/$package_file"; $PROCESSED_PACKAGES{$package}++; if (-f $filename) { push @FILES, $filename; process_module($package, $filename); last DIR; } } } warn "Methods: \n" . join("\n", keys %METHODS) . "\n" if ($verbose); sub process_module { my ($package, $path) = @_; no strict 'refs'; warn "Processing $package\n" if ($verbose); eval "use $package;"; open my $fh, "ctags -x $path |" or die "Can't open $path with ctags\n"; my @ctags_output = <$fh>; close $fh; my ($col_type, $col_name) = (3, 0); if (`ctags --version` =~ /Exuberant Ctags/i) { ($col_type, $col_name) = (1, 0); } foreach my $line (@ctags_output) { my @columns = split(/\s+/, $line); next if ($columns[$col_type] !~ 'sub'); my ($sub) = $columns[$col_name] =~ /([^:]+)$/; next if ($sub =~ /^_/); next if ($sub =~ /[A-Z]/); next if (grep /\b$sub\b/, @{$package . "::EXCLUDE_METHODS"}); my $type = "action"; $type = "test" if ($line =~ /$sub\s*:\s*Test/); $METHODS{$sub} = $type; } return if ($package eq 'Test::A8N::Fixture'); my @isa = @{$package . "::ISA"}; foreach my $base (@isa) { next if (exists($PROCESSED_PACKAGES{$base})); warn "Following inheritance tree to $base\n" if ($verbose); push @PACKAGES, $base; } } open my $of, ">$home/.fixtures" or die "Can't open ~/.fixtures for writing: $@\n"; foreach my $method (keys %METHODS) { my $method_name = $method; $method_name =~ s/_/ /g; printf $of qq{syn match fixture_%s "- %s[: ]"\n}, $METHODS{$method}, $method_name; printf $of qq{syn match fixture_%s "- %s\$"\n}, $METHODS{$method}, $method_name; } close $of or die "Can't close output file: $@\n";