bump version and update Changes for release
[gitmo/Moose.git] / lib / Moose / Util.pm
index 8a1517c..a617093 100644 (file)
@@ -5,10 +5,9 @@ use warnings;
 
 use Sub::Exporter;
 use Scalar::Util 'blessed';
-use Carp         'confess';
-use Class::MOP   0.57;
+use Class::MOP   0.60;
 
-our $VERSION   = '0.57';
+our $VERSION   = '0.72';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -22,6 +21,7 @@ my @exports = qw[
     resolve_metatrait_alias
     resolve_metaclass_alias
     add_method_modifier
+    english_list
 ];
 
 Sub::Exporter::setup_exporter({
@@ -73,7 +73,10 @@ sub search_class_by_role {
 sub apply_all_roles {
     my $applicant = shift;
 
-    confess "Must specify at least one role to apply to $applicant" unless @_;
+    unless (@_) {
+        require Moose;
+        Moose->throw_error("Must specify at least one role to apply to $applicant");
+    }
 
     my $roles = Data::OptList::mkopt( [@_] );
 
@@ -83,11 +86,16 @@ sub apply_all_roles {
         Class::MOP::load_class( $role_spec->[0] );
     }
 
-    ( $_->[0]->can('meta') && $_->[0]->meta->isa('Moose::Meta::Role') )
-        || confess "You can only consume roles, "
-        . $_->[0]
-        . " is not a Moose role"
-        foreach @$roles;
+    foreach my $role (@$roles) {
+        unless ( $role->[0]->can('meta')
+            && $role->[0]->meta->isa('Moose::Meta::Role') ) {
+
+            require Moose;
+            Moose->throw_error( "You can only consume roles, "
+                    . $role->[0]
+                    . " is not a Moose role" );
+        }
+    }
 
     if ( scalar @$roles == 1 ) {
         my ( $role, $params ) = @{ $roles->[0] };
@@ -120,25 +128,35 @@ sub get_all_init_args {
 }
 
 sub resolve_metatrait_alias {
-    resolve_metaclass_alias( @_, trait => 1 );
+    return resolve_metaclass_alias( @_, trait => 1 );
 }
 
-sub resolve_metaclass_alias {
-    my ( $type, $metaclass_name, %options ) = @_;
+{
+    my %cache;
 
-    if ( my $resolved = eval {
-        my $possible_full_name = 'Moose::Meta::' . $type . '::Custom::' . ( $options{trait} ? "Trait::" : "" ) . $metaclass_name;
+    sub resolve_metaclass_alias {
+        my ( $type, $metaclass_name, %options ) = @_;
 
-        Class::MOP::load_class($possible_full_name);
+        my $cache_key = $type . q{ } . ( $options{trait} ? '-Trait' : '' );
+        return $cache{$cache_key}{$metaclass_name}
+            if $cache{$cache_key}{$metaclass_name};
 
-        $possible_full_name->can('register_implementation')
-            ? $possible_full_name->register_implementation
-            : $possible_full_name;
-    } ) {
-        return $resolved;
-    } else {
-        Class::MOP::load_class($metaclass_name);
-        return $metaclass_name;
+        my $possible_full_name
+            = 'Moose::Meta::' 
+            . $type
+            . '::Custom::'
+            . ( $options{trait} ? "Trait::" : "" )
+            . $metaclass_name;
+
+        my $loaded_class = Class::MOP::load_first_existing_class(
+            $possible_full_name,
+            $metaclass_name
+        );
+
+        return $cache{$cache_key}{$metaclass_name}
+            = $loaded_class->can('register_implementation')
+            ? $loaded_class->register_implementation
+            : $loaded_class;
     }
 }
 
@@ -161,6 +179,19 @@ sub add_method_modifier {
     }
 }
 
+sub english_list {
+    my @items = sort @_;
+
+    return $items[0] if @items == 1;
+    return "$items[0] and $items[1]" if @items == 2;
+
+    my $tail = pop @items;
+    my $list = join ', ', @items;
+    $list .= ', and ' . $tail;
+
+    return $list;
+}
+
 1;
 
 __END__
@@ -190,7 +221,7 @@ This is a set of utility functions to help working with Moose classes, and
 is used internally by Moose itself. The goal is to provide useful functions
 that for both Moose users and Moose extenders (MooseX:: authors).
 
-This is a relatively new addition to the Moose toolchest, so ideas, 
+This is a relatively new addition to the Moose tool chest, so ideas, 
 suggestions and contributions to this collection are most welcome. 
 See the L<TODO> section below for a list of ideas for possible functions 
 to write.
@@ -218,7 +249,7 @@ Given an C<$applicant> (which can somehow be turned into either a
 metaclass or a metarole) and a list of C<@roles> this will do the 
 right thing to apply the C<@roles> to the C<$applicant>. This is 
 actually used internally by both L<Moose> and L<Moose::Role>, and the
-C<@roles> will be pre-processed through L<Data::OptList::mkopt>
+C<@roles> will be preprocessed through L<Data::OptList::mkopt>
 to allow for the additional arguments to be passed. 
 
 =item B<get_all_attribute_values($meta, $instance)>
@@ -245,6 +276,12 @@ to a full class name.
 
 =item B<add_method_modifier ($class_or_obj, $modifier_name, $args)>
 
+=item B<english_list(@items)>
+
+Given a list of scalars, turns them into a proper list in English
+("one and two", "one, two, three, and four"). This is used to help us
+make nicer error messages.
+
 =back
 
 =head1 TODO
@@ -277,7 +314,7 @@ Stevan Little
 
 =head1 COPYRIGHT AND LICENSE
 
-Copyright 2007-2008 by Infinity Interactive, Inc.
+Copyright 2007-2009 by Infinity Interactive, Inc.
 
 L<http://www.iinteractive.com>