+#!/usr/bin/perl -l
+use strict;
+#use warnings; # corelist and find throw tons of warnings
+use File::Find;
+use Module::CoreList;
+use SL::InstallationCheck;
+use Term::ANSIColor;
+
+my (%uselines, %modules, %supplied, %requires);
+
+# since the information which classes belong to a cpan distribution is not
+# easily obtained, I'll just hard code the bigger ones we use here. the same
+# hash will be filled later with information gathered from the source files.
+%requires = (
+  'DateTime' => {
+    'DateTime::Duration'                 => 1,
+    'DateTime::Infinite'                 => 1,
+  },
+  'Rose::DB::Object' => {
+   'Rose::DB::Object::ConventionManager' => 1,
+   'Rose::DB::Object::Manager'           => 1,
+   'Rose::DB::Object::Metadata'          => 1,
+  },
+  'Rose::Object' => {
+    'Rose::Object::MakeMethods::Generic' => 1,
+  },
+  'Template' => {
+    'Template::Constants'                => 1,
+    'Template::Exception'                => 1,
+    'Template::Iterator'                 => 1,
+    'Template::Plugin'                   => 1,
+    'Template::Plugin::Filter'           => 1,
+  },
+);
+
+find(sub {
+  return unless /(\.p[lm]|console)$/;
+
+  # remember modules shipped with Lx-Office
+  $supplied{modulize($File::Find::name)}++
+    if $File::Find::dir =~ m#modules/#;
+
+  open my $fh, '<', $_ or warn "can't open $_: $!";
+  while (<$fh>) {
+    chomp;
+    next if !/^use /;
+    next if /SL::/;
+    next if /Support::Files/; # our own test support module
+    next if /use (warnings|strict|vars|lib|constant|utf8)/;
+
+    my ($useline) = m/^use\s+(.*?)$/;
+
+    next if  $useline =~ /^[\d._]+;/; # skip version requirements
+    next if !$useline;
+
+    $uselines{$useline} ||= [];
+    push @{ $uselines{$useline} }, $File::Find::name;
+  }
+}, '.');
+
+for my $useline (keys %uselines) {
+  $useline =~ s/#.*//; # kill comments
+
+  # modules can be loaded implicitly with use base qw(Module) or use parent
+  # 'Module'. catch these:
+  my ($module, $args) = $useline =~ /
+    (?:
+      (?:base|parent)
+      \s
+      (?:'|"|qw.)
+    )?                 # optional parent block
+    ([\w:]+)           # the module
+    (.*)               # args
+  /ix;
+
+  # some comments looks very much like use lines
+  # try to get rid of them
+  next if $useline =~ /^it like a normal Perl node/;   # YAML::Dump comment
+  next if $useline =~ /^most and offer that in a small/; # YAML
+
+  my $version = Module::CoreList->first_release($module);
+  $modules{$module} = $supplied{$module}     ? 'included'
+                    : $version               ? sprintf '%2.6f', $version
+                    : is_documented($module) ? 'required'
+                    : '!missing';
+
+  # build requirement tree
+  for my $file (@{ $uselines{$useline} }) {
+    next if $file =~ /\.pl$/;
+    my $orig_module = modulize($file);
+    $requires{$orig_module} ||= {};
+    $requires{$orig_module}{$module}++;
+  }
+}
+
+# build transitive closure for documented dependancies
+my $changed = 1;
+while ($changed) {
+  $changed = 0;
+  for my $src_module (keys %requires) {
+    for my $dst_module (keys %{ $requires{$src_module} }) {
+      if (   $modules{$src_module} =~ /^required/
+          && $modules{$dst_module} eq '!missing') {
+        $modules{$dst_module} = "required"; # . ", via $src_module";
+        $changed = 1;
+      }
+    }
+  }
+}
+
+print sprintf "%8s : %s", color_text($modules{$_}), $_
+  for sort {
+       $modules{$a} cmp $modules{$b}
+    ||          $a  cmp $b
+  } keys %modules;
+
+sub modulize {
+  for (my ($name) = @_) {
+    s#^./modules/\w+/##;
+    s#^./##;
+    s#.pm$##;
+    s#/#::#g;
+    return $_;
+  }
+}
+
+sub is_documented {
+  my ($module) = @_;
+  grep { $_->{name} eq $module } @SL::InstallationCheck::required_modules;
+}
+
+sub color_text {
+  my ($text) = @_;
+  return color(get_color($text)) . $text . color('reset');
+}
+
+sub get_color {
+  for (@_) {
+    return 'yellow' if /^5./ && $_ > 5.008;
+    return 'green'  if /^5./;
+    return 'green'  if /^included/;
+    return 'red'    if /^!missing/;
+    return 'yellow';
+  }
+}
+
+1;
+
+__END__
+