SWF-NeedsRecompile

 view release on metacpan or  search on metacpan

lib/SWF/NeedsRecompile.pm  view on Meta::CPAN

         {
            _log(2, "do deps for $checkfile");
            $depends{$checkfile} = [];
            my $content = File::Slurp::read_file($checkfile);
            my %imported_files;
            my %seen;

            if ($checkfile =~ m/[.]fla\z/ixms)
            {
               # HACK: use C regexp because the ECMAScript regexp can
               # cause an infinite loop on some .fla files.
               # See BUGS AND LIMITATIONS
               $content =~ s/$RE{comment}{C}//gxms;
            }
            else
            {
               $content =~ s/$RE{comment}{ECMAScript}//gxms;
            }

            # check for include and import statements and instantiations via "new"
            my @deps = (
               _get_includes($checkfile, \$content, \%seen),
               _get_imports($checkfile, \$content, \@paths, \%imported_files, \%seen),
               _get_instantiations($checkfile, \$content, \@paths, \%imported_files, \%seen),
            );
            my @problems = map { @{$_} } grep { ref $_ } @deps;
            if (@problems > 0)
            {
               _log(1, "Failed to locate dependencies in $checkfile: @problems");
               $up_to_date = 0;
               last;
            }
            $depends{$checkfile} = \@deps;
         }
         push @check, @{$depends{$checkfile}};
      }

      if (!$up_to_date)
      {
         push @needs_recompile, $file;
      }
   }
   return @needs_recompile;
}

sub _get_fla_classpaths
{
   my $fla = shift;

   my @paths;
   if (-f $fla && (my $content = File::Slurp::read_file($fla, binmode => ':raw')))
   {
      # Limitation: the path must be purely ASCII or this doesn't work
      my @matches = $content =~ m/V\0e\0c\0t\0o\0r\0:\0:\0P\0a\0c\0k\0a\0g\0e\0[ ]\0P\0a\0t\0h\0s\0....((?:[^\0]\0)*)/gxms;
      my %seen;
      for my $match (@matches)
      {
         # Hack: downgrade unicode to ascii
         $match =~ s/\0//gxms;
         next if q{} eq $match;
         my @search_paths = split m/;/xms, $match;
         require File::Spec;
         for my $path (@search_paths)
         {
            if (!File::Spec->file_name_is_absolute($path))
            {
               my $root = [File::Spec->splitpath($fla)]->[1];
               if ($root)
               {
                  $path = File::Spec->rel2abs($path, $root);
               }
            }
            next if ($seen{$path}++);
            push @paths, $path;
         }
      }
      _log(2, "FLA Paths: @paths");
   }
   return @paths;
}

sub _get_includes
{
   my $checkfile   = shift;
   my $content_ref = shift;
   my $seen_ref    = shift;

   my @deps;

   # Check both ascii and ascii-unicode, supporting Flash MX and 2004 .fla files
   # This will fail for non-ascii filenames
   my @matches = ${$content_ref} =~ m/\#\0?i\0?n\0?c\0?l\0?u\0?d\0?e\0?(?:\s\0?)+["]\0?([^"\r\n]+?)["]/gxms; ## no critic (EscapedMeta)
   foreach my $inc (@matches)
   {
      next if ($seen_ref->{$inc}++); # speedup
      # This is a hack.  Strip real Unicode down to ASCII
      $inc =~ s/\0//gxms;
      if ($inc)
      {
         my $file = $inc;
         if (! -f $file)
         {
            if (! File::Spec->file_name_is_absolute($file))
            {
               my $dir = [File::Spec->splitpath($checkfile)]->[1];
               if ($dir)
               {
                  $file = File::Spec->rel2abs($file, $dir);
               }
            }
            return [$inc] if (! -f $file);
         }
         push @deps, $file;
         _log(2, "#include $inc from $checkfile");
      }
   }
   return @deps;
}

sub _get_imports
{
   my $checkfile         = shift;
   my $content_ref       = shift;
   my $fla_path_ref      = shift;
   my $imported_file_ref = shift;
   my $seen_ref          = shift;

   my @deps;
   my @matches = ${$content_ref} =~ m/i\0?m\0?p\0?o\0?r\0?t\0?(?:\s\0?)+((?:[^\;\0\s]\0?)+);/gxms;
   foreach my $imp (@matches)
   {
      next if ($seen_ref->{$imp}++);    # speedup
      # This is a hack.  Strip real Unicode down to ASCII
      $imp =~ s/\0//gxms;
      _log(2, "import $imp from $checkfile");
      my $found = 0;
      foreach my $dir (@{$fla_path_ref}, as_classpath())
      {
         my $f = File::Spec->catdir(File::Spec->splitdir($dir), split m/[.]/xms, $imp);
         if ($f =~ m/[*]\z/xms)
         {
            my @d = File::Spec->splitdir($f);
            pop @d;
            $f = File::Spec->catdir(@d);
            if (-d $f)
            {
               my @as = grep { m/[.]as\z/xms } File::Slurp::read_dir($f);

               for my $file (@as)
               {
                  $imported_file_ref->{$file} = 1;
               }
               @as = map { File::Spec->catfile($f, $_) } @as;

               for my $file (@as)
               {
                  _log(2, "  import $file from $checkfile");
               }
               push @deps, @as;
            }
            $found = 1;
         }
         else
         {
            $f .= '.as';
            if (-f $f)
            {
               my @p = split m/[.]/xms, $imp;
               $imported_file_ref->{$p[-1] . '.as'} = 1;
               _log(2, "  import $f from $checkfile");
               push @deps, $f;
               $found = 1;
               last;
            }
         }
      }
      return [$imp] if (!$found);
   }
   return @deps;
}

sub _get_instantiations
{
   my $checkfile         = shift;
   my $content_ref       = shift;
   my $fla_path_ref      = shift;
   my $imported_file_ref = shift;
   my $seen_ref          = shift;

   # Get a list of all classes defined in this file
   my @classes;
   my @class_matches = ${$content_ref} =~ m/c\0?l\0?a\0?s\0?s\0?(?:\s\0?)+((?:[^;\s\0]\0?)+)/gxms;
   for my $class_match (@class_matches)
   {
      $class_match =~ s/\0//gxms;
      push @classes, $class_match;
   }

   my @deps;
   my @matches = ${$content_ref} =~ m/n\0?e\0?w\0?(?:\s\0?)+((?:[\w.]\0?)+)[(]/gxms;
   foreach my $imp (@matches)
   {
      next if ($seen_ref->{$imp}++); # speedup
      # This is a hack.  Strip real Unicode down to ASCII
      $imp =~ s/\0//gxms;
      next if ($exceptions{$imp});
      _log(2, "instance $imp from $checkfile");
      next if ($imported_file_ref->{$imp . '.as'});
      # Is this class implemented in this very file?
      next if any { $_ eq $imp || m/[.]\Q$imp\E\z/xms } @classes;
      my $found = 0;
      foreach my $dir (@{$fla_path_ref}, as_classpath())
      {
         my $f = File::Spec->catdir(File::Spec->splitdir($dir), split m/[.]/xms, $imp);
         $f .= '.as';
         if (-f $f)
         {
            _log(2, "  instance $f from $checkfile");
            push @deps, $f;
            $found = 1;
            last;
         }
      }
      return [$imp] if (!$found);
   }
   return @deps;
}

=item $pkg->as_classpath()

Returns a list of Classpath directories specified globally in Flash.

=cut

sub as_classpath
{
   if (!$cached_as_classpath)
   {
      my $prefs_file = flash_prefs_path();
      if (!$prefs_file || ! -f $prefs_file)
      {
         #_log(2, 'Failed to locate the Flash prefs file');
         return q{.};
      }

      my $conf_dir = flash_config_path();
      for (File::Slurp::read_file($prefs_file))
      {
         if (m/<Package_Paths>(.*?)<\/Package_Paths>/xms)
         {
            my $cp = $1;
            my @dirs = split /;/xms, $cp;
            for (@dirs)
            {
               if (!$conf_dir)
               {
                  _log(2, "Failed to identify the UserConfig dir for '$_'");
               }
               else
               {
                  s/[$][(]UserConfig[)]/$conf_dir/xms;
               }
            }
            $cached_as_classpath = \@dirs;
            _log(2, "Classpath: @{$cached_as_classpath}");
            last;
         }
      }
   }
   return @{$cached_as_classpath};
}

=item $pkg->flash_prefs_path()



( run in 0.808 second using v1.01-cache-2.11-cpan-71847e10f99 )