earlier error reporting, with tests
[p5sagit/Package-Variant.git] / lib / Package / Variant.pm
index b0c2698..bd39d4f 100644 (file)
@@ -1,9 +1,38 @@
 package Package::Variant;
 
 use strictures 1;
+use Carp qw( croak );
 
 our %Variable;
 
+my $sanitize_importing = sub {
+  my ($me, $spec) = @_;
+  return []
+    unless defined $spec;
+  return [map {
+    my $import_args = $spec->{$_};
+    croak sprintf q{Import argument list for '%s' is not an array ref},
+      $_,
+      unless ref($import_args) and ref($import_args) eq 'ARRAY';
+    [$_ => $import_args];
+  } keys %$spec]
+    if ref $spec eq 'HASH';
+  croak q{The 'importing' option has to be either a hash or array ref}
+    unless ref $spec eq 'ARRAY';
+  my @specced = @$spec;
+  my @imports;
+  while (@specced) {
+    my $key = shift @specced;
+    push @imports, [
+      $key,
+      (ref($specced[0]) and ref($specced[0]) eq 'ARRAY')
+        ? shift(@specced)
+        : [],
+    ];
+  }
+  return \@imports;
+};
+
 sub import {
   my $target = caller;
   my $me = shift;
@@ -14,7 +43,10 @@ sub import {
   no strict 'refs';
   $Variable{$variable} = {
     anon => $anon,
-    args => \%args,
+    args => {
+      %args,
+      importing => $me->$sanitize_importing($args{importing}),
+    },
     subs => {
       map +($_ => sub {}), @{$args{subs}||[]},
     },
@@ -42,12 +74,19 @@ sub import {
 sub build_variant_of {
   my ($me, $variable, @args) = @_;
   my $variant_name = "${variable}::_Variant_".++$Variable{$variable}{anon};
-  my $import = $Variable{$variable}{args}{importing} || {};
+  my $import = $Variable{$variable}{args}{importing};
   my $setup = join("\n",
     "package ${variant_name};",
     (map sprintf(
-      q!use %s @{$import->{'%s'}||[]};!, $_, quotemeta($_),
-    ), keys %$import),
+      q!use %s %s;!,
+      $import->[$_][0],
+      scalar(@{$import->[$_][1]})
+        ? sprintf(
+          q!@{$import->[%d][1]}!,
+          $_,
+        )
+        : '',
+    ), 0..$#$import),
     "1;",
   );
   eval $setup
@@ -78,7 +117,7 @@ Package::Variant - Parameterizable packages
   use strictures 1;
   use Package::Variant
     # what modules to 'use'
-    importing => { 'Moo::Role' => [] },
+    importing => ['Moo::Role'],
     # proxied subroutines
     subs => [qw( has around before after extends )],
 
@@ -131,12 +170,13 @@ describe how you intend to build your variations.
     importing => { $package => \@import_arguments, ... },
     subs      => [ @proxied_subroutine_names ];
 
-The L</importing> option needs to be a hash reference with package names
-to be C<use>d as keys, and array references containing the import
-arguments as values. These packages will be imported into every new
+The L</importing> option needs to be a hash or array reference with
+package names to be C<use>d as keys, and array references containing the
+import arguments as values. These packages will be imported into every new
 variant, and need to set up every declarative subroutine you require to
 build your variable package. The next option will allow you to use these
-functions.
+functions. See L</importing> for more options. You can omit empty import
+argument lists when passing an array reference.
 
 The L</subs> option is an array reference of subroutine names that are
 exported by the packages specified with L</importing>. These subroutines
@@ -208,6 +248,23 @@ containing import arguments. The packages will be C<use>d with the given
 arguments by every variation before the L</make_variant> method is asked
 to create the package.
 
+If import order is important to you, you can also pass the C<importing>
+arguments as a flat array reference:
+
+  use Package::Variant
+    importing => [ 'PackageA', 'PackageB' ];
+
+  # same as
+  use Package::Variant
+    importing => [ 'PackageA' => [], 'PackageB' => [] ];
+
+  # or
+  use Package::Variant
+    importing => { 'PackageA' => [], 'PackageB' => [] };
+
+The import method will be called even if the list of import arguments is
+empty or not specified,
+
 =head2 subs
 
 An array reference of strings listing the names of subroutines that should