Merge branch 'master' into attribute_helpers
Hans Dieter Pearcey [Fri, 26 Jun 2009 17:26:18 +0000 (13:26 -0400)]
Conflicts:
Changes

60 files changed:
Changes
Makefile.PL
README
lib/Moose.pm
lib/Moose/Error/Confess.pm
lib/Moose/Error/Croak.pm
lib/Moose/Error/Default.pm
lib/Moose/Exporter.pm
lib/Moose/Manual/Delta.pod
lib/Moose/Meta/Attribute.pm
lib/Moose/Meta/Class.pm
lib/Moose/Meta/Class/Immutable/Trait.pm
lib/Moose/Meta/Instance.pm
lib/Moose/Meta/Method.pm
lib/Moose/Meta/Method/Accessor.pm
lib/Moose/Meta/Method/Augmented.pm
lib/Moose/Meta/Method/Constructor.pm
lib/Moose/Meta/Method/Delegation.pm
lib/Moose/Meta/Method/Destructor.pm
lib/Moose/Meta/Method/Overridden.pm
lib/Moose/Meta/Role.pm
lib/Moose/Meta/Role/Application.pm
lib/Moose/Meta/Role/Application/RoleSummation.pm
lib/Moose/Meta/Role/Application/ToClass.pm
lib/Moose/Meta/Role/Application/ToInstance.pm
lib/Moose/Meta/Role/Application/ToRole.pm
lib/Moose/Meta/Role/Composite.pm
lib/Moose/Meta/Role/Method.pm
lib/Moose/Meta/Role/Method/Conflicting.pm
lib/Moose/Meta/Role/Method/Required.pm
lib/Moose/Meta/TypeCoercion.pm
lib/Moose/Meta/TypeCoercion/Union.pm
lib/Moose/Meta/TypeConstraint.pm
lib/Moose/Meta/TypeConstraint/Class.pm
lib/Moose/Meta/TypeConstraint/DuckType.pm
lib/Moose/Meta/TypeConstraint/Enum.pm
lib/Moose/Meta/TypeConstraint/Parameterizable.pm
lib/Moose/Meta/TypeConstraint/Parameterized.pm
lib/Moose/Meta/TypeConstraint/Registry.pm
lib/Moose/Meta/TypeConstraint/Role.pm
lib/Moose/Meta/TypeConstraint/Union.pm
lib/Moose/Object.pm
lib/Moose/Role.pm
lib/Moose/Util.pm
lib/Moose/Util/MetaRole.pm
lib/Moose/Util/TypeConstraints.pm
lib/Moose/Util/TypeConstraints/OptimizedConstraints.pm
lib/Test/Moose.pm
lib/oose.pm
t/010_basics/022_moose_exporter_groups.t [new file with mode: 0755]
t/020_attributes/001_attribute_reader_generation.t
t/020_attributes/005_attribute_does.t
t/020_attributes/026_attribute_without_any_methods.t
t/020_attributes/027_accessor_override_method.t [new file with mode: 0644]
t/030_roles/002_role.t
t/030_roles/041_empty_method_modifiers_meta_bug.t [new file with mode: 0644]
t/040_type_constraints/003_util_std_type_constraints.t
t/040_type_constraints/024_role_type_constraint.t
xt/author/pod_coverage.t
xt/author/pod_spell.t

diff --git a/Changes b/Changes
index bce5ce1..5441466 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,23 +1,49 @@
 Also see Moose::Manual::Delta for more details of, and workarounds
 for, noteworthy changes.
 
-0.84
+0.85
     * Moose::Meta::Attribute
-      - When adding an attribute to a metaclass, if the attribute has no
-        associated methods, it will give a deprecation warning. (hdp)
+      - The warning for 'no associated methods' is now split out into the
+        check_associated_methods method, so that extensions can safely call
+        'after install_accessors => ...'. (hdp)
+      - Move currying syntax for delegation in from AttributeHelpers. (hdp)
+
+0.84 Fri, Jun 26, 2009
+    * Moose::Role
+      - has now sets definition_context for attributes defined in
+        roles. (doy)
+
+    * Moose::Meta::Attribute
+      - When adding an attribute to a metaclass, if the attribute has
+        no associated methods, it will give a deprecation
+        warning. (hdp)
       - Methods generated by delegation were not being added to
         associated_methods. (hdp)
-      - Move currying syntax for delegation in from AttributeHelpers. (hdp)
+      - Attribute accessors (reader, writer, accessor, predicate,
+        clearer) now warn if they overwrite an existing method. (doy)
+      - Attribute constructors now warn very noisily about unknown (or
+        mispelled) arguments
+
+    * Moose::Util::TypeConstraints
+      - Deprecated the totally useless Role type name, which just
+        checked if $object->can('does'). Note that this is _not_ the
+        same as a type created by calling role_type('RoleName').
 
     * Moose::Util::TypeConstraints
     * Moose::Meta::TypeConstraint::DuckType
       - Reify duck type from a regular subtype into an actual class
         (Sartak)
+        - Document this because Sartak did all my work for me
+          (perigrin)
 
     * Moose::Meta::Attribute
       - Allow Moose::Meta::TypeConstraint::DuckType in handles, since
         it is just a list of methods (Sartak)
 
+    * Moose::Meta::Role
+      - The get_*_method_modifiers methods would die if the role had
+        no modifiers of the given type (Robert Buels).
+
 0.83 Tue, Jun 23, 2009
     * Moose::Meta::Class
       - Fix _construct_instance not setting the special __MOP__ object
@@ -1825,16 +1851,16 @@ for, noteworthy changes.
       - added all the meta classes to the immutable list and
         set it to inline the accessors
       - fix import to allow Sub::Exporter like { into => }
-           and { into_level => } (perigrin)
+            and { into_level => } (perigrin)
       - exposed and documented init_meta() to allow better
-           embedding and extending of Moose (perigrin)
+            embedding and extending of Moose (perigrin)
 
-       * t/
-         - complete re-organization of the test suite
-         - added some new tests as well
-         - finally re-enabled the Moose::POOP test since
-           the new version of DBM::Deep now works again
-           (thanks rob)
+        * t/
+          - complete re-organization of the test suite
+          - added some new tests as well
+          - finally re-enabled the Moose::POOP test since
+            the new version of DBM::Deep now works again
+            (thanks rob)
 
     * Moose::Meta::Class
       - fixed very odd and very nasty recursion bug with
@@ -2553,9 +2579,9 @@ for, noteworthy changes.
       - Type constraints now survive runtime reloading
         - added test for this
 
-       * Moose::Meta::Class
-         - fixed the way attribute defaults are handled
-           during instance construction (bug found by chansen)
+        * Moose::Meta::Class
+          - fixed the way attribute defaults are handled
+            during instance construction (bug found by chansen)
 
     * Moose::Meta::Attribute
       - read-only attributes now actually enforce their
@@ -2603,8 +2629,8 @@ for, noteworthy changes.
 
     * Moose::Meta::TypeConstraint
     * Moose::Meta::TypeCoercion
-         - type constraints and coercions are now
-           full fledges meta-objects
+          - type constraints and coercions are now
+            full fledges meta-objects
 
 0.01 Wed. March 15, 2006
     - Moooooooooooooooooose!!!
index 2c72d29..3574a1a 100644 (file)
@@ -14,7 +14,7 @@ requires 'Scalar::Util'     => '1.19';
 requires 'Carp';
 requires 'Class::MOP'       => '0.88';
 requires 'List::MoreUtils'  => '0.12';
-requires 'Sub::Exporter'    => '0.972';
+requires 'Sub::Exporter'    => '0.980';
 requires 'Task::Weaken'     => '0';
 requires 'Data::OptList'    => '0';
 requires 'Sub::Name'        => '0';
diff --git a/README b/README
index 72b5774..bd183de 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Moose version 0.83
+Moose version 0.84
 ===========================
 
 See the individual module documentation for more information
index 15cf38b..2372d86 100644 (file)
@@ -2,7 +2,7 @@ package Moose;
 
 use 5.008;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -32,13 +32,6 @@ use Moose::Meta::Role::Application::ToInstance;
 use Moose::Util::TypeConstraints;
 use Moose::Util ();
 
-sub _caller_info {
-    my $level = @_ ? ($_[0] + 1) : 2;
-    my %info;
-    @info{qw(package file line)} = caller($level);
-    return \%info;
-}
-
 sub throw_error {
     # FIXME This
     shift;
@@ -68,7 +61,7 @@ sub has {
     Moose->throw_error('Usage: has \'name\' => ( key => value, ... )')
         if @_ % 2 == 1;
 
-    my %options = ( definition_context => _caller_info(), @_ );
+    my %options = ( definition_context => Moose::Util::_caller_info(), @_ );
     my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ];
     Class::MOP::Class->initialize($class)->add_attribute( $_, %options ) for @$attrs;
 }
@@ -469,7 +462,7 @@ B<NOTE:> Triggers will only fire when you B<assign> to the attribute,
 either in the constructor, or using the writer. Default and built values will
 B<not> cause the trigger to be fired.
 
-=item I<handles =E<gt> ARRAY | HASH | REGEXP | ROLE | CODE>
+=item I<handles =E<gt> ARRAY | HASH | REGEXP | ROLE | DUCKTYPE | CODE>
 
 The I<handles> option provides Moose classes with automated delegation features.
 This is a pretty complex and powerful option. It accepts many different option
@@ -573,6 +566,14 @@ methods of the role and any required methods of the role. It should be noted
 that this does B<not> include any method modifiers or generated attribute
 methods (which is consistent with role composition).
 
+=item C<DUCKTYPE>
+
+With the duck type option, you pass a duck type object whose "interface" then
+becomes the list of methods to handle. The "interface" can be defined as; the
+list of methods passed to C<duck_type> to create a duck type object. For more
+information on C<duck_type> please check
+L<Moose::Util::TypeConstraint|Moose::Util::TypeConstraint>.
+
 =item C<CODE>
 
 This is the option to use when you really want to do something funky. You should
index a3a5b11..50fbab9 100644 (file)
@@ -3,7 +3,7 @@ package Moose::Error::Confess;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 7b18eb4..78c82ac 100644 (file)
@@ -3,7 +3,7 @@ package Moose::Error::Croak;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 3d05ae9..7b7f607 100644 (file)
@@ -3,7 +3,7 @@ package Moose::Error::Default;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 8151e6d..82bfe11 100644 (file)
@@ -3,14 +3,14 @@ package Moose::Exporter;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
 use Class::MOP;
 use List::MoreUtils qw( first_index uniq );
 use Moose::Util::MetaRole;
-use Sub::Exporter;
+use Sub::Exporter 0.980;
 use Sub::Name qw(subname);
 
 my %EXPORT_SPEC;
@@ -38,14 +38,14 @@ sub build_import_methods {
 
     my $export_recorder = {};
 
-    my ( $exports, $is_removable )
+    my ( $exports, $is_removable, $groups )
         = $class->_make_sub_exporter_params(
         [ @exports_from, $exporting_package ], $export_recorder );
 
     my $exporter = Sub::Exporter::build_exporter(
         {
             exports => $exports,
-            groups  => { default => [':all'] }
+            groups  => { default => [':all'], %$groups }
         }
     );
 
@@ -107,6 +107,7 @@ sub _make_sub_exporter_params {
     my $packages          = shift;
     my $export_recorder   = shift;
 
+    my %groups;
     my %exports;
     my %is_removable;
 
@@ -114,6 +115,15 @@ sub _make_sub_exporter_params {
         my $args = $EXPORT_SPEC{$package}
             or die "The $package package does not use Moose::Exporter\n";
 
+        # one group for each 'also' package
+        $groups{$package} = [
+            @{ $args->{with_caller} || [] },
+            @{ $args->{with_meta}   || [] },
+            @{ $args->{as_is}       || [] },
+            map ":$_",
+            keys %{ $args->{groups} || {} }
+        ];
+
         for my $name ( @{ $args->{with_caller} } ) {
             my $sub = do {
                 no strict 'refs';
@@ -131,6 +141,23 @@ sub _make_sub_exporter_params {
             $is_removable{$name} = 1;
         }
 
+        for my $name ( @{ $args->{with_meta} } ) {
+            my $sub = do {
+                no strict 'refs';
+                \&{ $package . '::' . $name };
+            };
+
+            my $fq_name = $package . '::' . $name;
+
+            $exports{$name} = $class->_make_wrapped_sub_with_meta(
+                $fq_name,
+                $sub,
+                $export_recorder,
+            );
+
+            $is_removable{$name} = 1;
+        }
+
         for my $name ( @{ $args->{as_is} } ) {
             my $sub;
 
@@ -165,9 +192,26 @@ sub _make_sub_exporter_params {
 
             $exports{$name} = sub {$sub};
         }
+
+        for my $name ( keys %{ $args->{groups} } ) {
+            my $group = $args->{groups}{$name};
+
+            if (ref $group eq 'CODE') {
+                $groups{$name} = $class->_make_wrapped_group(
+                    $package,
+                    $group,
+                    $export_recorder,
+                    \%exports,
+                    \%is_removable
+                );
+            }
+            elsif (ref $group eq 'ARRAY') {
+                $groups{$name} = $group;
+            }
+        }
     }
 
-    return ( \%exports, \%is_removable );
+    return ( \%exports, \%is_removable, \%groups );
 }
 
 our $CALLER;
@@ -197,6 +241,76 @@ sub _make_wrapped_sub {
     };
 }
 
+sub _make_wrapped_sub_with_meta {
+    my $self            = shift;
+    my $fq_name         = shift;
+    my $sub             = shift;
+    my $export_recorder = shift;
+
+    return sub {
+        my $caller = $CALLER;
+
+        my $wrapper = $self->_late_curry_wrapper($sub, $fq_name,
+            sub { Class::MOP::class_of(shift) } => $caller);
+
+        my $sub = subname($fq_name => $wrapper);
+
+        $export_recorder->{$sub} = 1;
+
+        return $sub;
+    };
+}
+
+sub _make_wrapped_group {
+    my $class           = shift;
+    my $package         = shift; # package calling use Moose::Exporter
+    my $sub             = shift;
+    my $export_recorder = shift;
+    my $keywords        = shift;
+    my $is_removable    = shift;
+
+    return sub {
+        my $caller = $CALLER; # package calling use PackageUsingMooseExporter -group => {args}
+
+        # there are plenty of ways to deal with telling the code which
+        # package it lives in. the last arg (collector hashref) is
+        # otherwise unused, so we'll stick the original package in
+        # there and act like 'with_caller' by putting the calling
+        # package name as the first arg
+        $_[0] = $caller;
+        $_[3]{from} = $package;
+
+        my $named_code = $sub->(@_);
+        $named_code ||= { };
+
+        # send invalid return value error up to Sub::Exporter
+        unless (ref $named_code eq 'HASH') {
+            return $named_code;
+        }
+
+        for my $name (keys %$named_code) {
+            my $code = $named_code->{$name};
+
+            my $fq_name = $package . '::' . $name;
+            my $wrapper = $class->_curry_wrapper(
+                $code,
+                $fq_name,
+                $caller
+            );
+
+            my $sub = subname( $fq_name => $wrapper );
+            $named_code->{$name} = $sub;
+
+            # mark each coderef as ours
+            $keywords->{$name} = 1;
+            $is_removable->{$name} = 1;
+            $export_recorder->{$sub} = 1;
+        }
+
+        return $named_code;
+    };
+}
+
 sub _curry_wrapper {
     my $class   = shift;
     my $sub     = shift;
@@ -212,6 +326,27 @@ sub _curry_wrapper {
     return $wrapper;
 }
 
+sub _late_curry_wrapper {
+    my $class   = shift;
+    my $sub     = shift;
+    my $fq_name = shift;
+    my $extra   = shift;
+    my @ex_args = @_;
+
+    my $wrapper = sub {
+        # resolve curried arguments at runtime via this closure
+        my @curry = ( $extra->( @ex_args ) );
+        return $sub->(@curry, @_);
+    };
+
+    if (my $proto = prototype $sub) {
+        # XXX - Perl's prototype sucks. Use & to make set_prototype
+        # ignore the fact that we're passing "private variables"
+        &Scalar::Util::set_prototype($wrapper, $proto);
+    }
+    return $wrapper;
+}
+
 sub _make_import_sub {
     shift;
     my $exporting_package = shift;
index e12d1f2..5cfee58 100644 (file)
@@ -16,6 +16,13 @@ feature.  If you encounter a problem and have a solution but don't see
 it documented here, or think we missed an important feature, please
 send us a patch.
 
+=head1 Version 0.84
+
+The C<Role> type has been deprecated. On its own, it was useless,
+since it just checked C<< $object->can('does') >>. If you were using
+it as a parent type, just call C<role_type('Role::Name')> to create an
+appropriate type instead.
+
 =head1 Version 0.78
 
 C<use Moose::Exporter;> now imports C<strict> and C<warnings> into packages
index 07598ac..5dce132 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Scalar::Util 'blessed', 'weaken';
 use overload     ();
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 our $AUTHORITY = 'cpan:STEVAN';
 
 use Moose::Meta::Method::Accessor;
@@ -78,28 +78,45 @@ sub throw_error {
 sub new {
     my ($class, $name, %options) = @_;
     $class->_process_options($name, \%options) unless $options{__hack_no_process_options}; # used from clone()... YECHKKK FIXME ICKY YUCK GROSS
+    
+    delete $options{__hack_no_process_options};
+
+    my %attrs =
+        ( map { $_ => 1 }
+          grep { defined }
+          map { $_->init_arg() }
+          $class->meta()->get_all_attributes()
+        );
+
+    my @bad = sort grep { ! $attrs{$_} }  keys %options;
+
+    if (@bad)
+    {
+        Carp::cluck "Found unknown argument(s) passed to '$name' attribute constructor in '$class': @bad";
+    }
+
     return $class->SUPER::new($name, %options);
 }
 
 sub interpolate_class_and_new {
-    my ($class, $name, @args) = @_;
+    my ($class, $name, %args) = @_;
 
-    my ( $new_class, @traits ) = $class->interpolate_class(@args);
+    my ( $new_class, @traits ) = $class->interpolate_class(\%args);
 
-    $new_class->new($name, @args, ( scalar(@traits) ? ( traits => \@traits ) : () ) );
+    $new_class->new($name, %args, ( scalar(@traits) ? ( traits => \@traits ) : () ) );
 }
 
 sub interpolate_class {
-    my ($class, %options) = @_;
+    my ($class, $options) = @_;
 
     $class = ref($class) || $class;
 
-    if ( my $metaclass_name = delete $options{metaclass} ) {
+    if ( my $metaclass_name = delete $options->{metaclass} ) {
         my $new_class = Moose::Util::resolve_metaclass_alias( Attribute => $metaclass_name );
 
         if ( $class ne $new_class ) {
             if ( $new_class->can("interpolate_class") ) {
-                return $new_class->interpolate_class(%options);
+                return $new_class->interpolate_class($options);
             } else {
                 $class = $new_class;
             }
@@ -108,7 +125,7 @@ sub interpolate_class {
 
     my @traits;
 
-    if (my $traits = $options{traits}) {
+    if (my $traits = $options->{traits}) {
         my $i = 0;
         while ($i < @$traits) {
             my $trait = $traits->[$i++];
@@ -226,7 +243,7 @@ sub clone_and_inherit_options {
     # so we can ignore it for them.
     # - SL
     if ($self->can('interpolate_class')) {
-        ( $actual_options{metaclass}, my @traits ) = $self->interpolate_class(%options);
+        ( $actual_options{metaclass}, my @traits ) = $self->interpolate_class(\%options);
 
         my %seen;
         my @all_traits = grep { $seen{$_}++ } @{ $self->applied_traits || [] }, @traits;
@@ -245,7 +262,7 @@ sub clone_and_inherit_options {
 sub clone {
     my ( $self, %params ) = @_;
 
-    my $class = $params{metaclass} || ref $self;
+    my $class = delete $params{metaclass} || ref $self;
 
     my ( @init, @non_init );
 
@@ -541,17 +558,39 @@ sub install_accessors {
     my $self = shift;
     $self->SUPER::install_accessors(@_);
     $self->install_delegation if $self->has_handles;
+    return;
+}
+
+sub check_associated_methods {
+    my $self = shift;
     unless (
         @{ $self->associated_methods }
         || ($self->_is_metadata || '') eq 'bare'
     ) {
         Carp::cluck(
-            'Attribute (' . $self->name . ') has no associated methods'
+            'Attribute (' . $self->name . ') of class '
+            . $self->associated_class->name
+            . ' has no associated methods'
             . ' (did you mean to provide an "is" argument?)'
             . "\n"
         )
     }
-    return;
+}
+
+sub _process_accessors {
+    my $self = shift;
+    my ($type, $accessor, $generate_as_inline_methods) = @_;
+    $accessor = (keys %$accessor)[0] if (ref($accessor)||'') eq 'HASH';
+    my $method = $self->associated_class->get_method($accessor);
+    if ($method && !$method->isa('Class::MOP::Method::Accessor')
+     && (!$self->definition_context
+      || $method->package_name eq $self->definition_context->{package})) {
+        Carp::cluck(
+            "You cannot overwrite a locally defined method ($accessor) with "
+          . "an accessor"
+        );
+    }
+    $self->SUPER::_process_accessors(@_);
 }
 
 sub remove_accessors {
@@ -799,7 +838,7 @@ name as the attribute, and a C<writer> with the name you provided.
 Use 'bare' when you are deliberately not installing any methods
 (accessor, reader, etc.) associated with this attribute; otherwise,
 Moose will issue a deprecation warning when this attribute is added to a
-metaclass.
+metaclass.  See L</check_associated_methods>.
 
 =item * isa => $type
 
@@ -1031,6 +1070,13 @@ Given a value, this method returns true if the value is valid for the
 attribute's type constraint. If the value is not valid, it throws an
 error.
 
+=item B<< $attr->check_associated_methods >>
+
+This method makes sure that either an explicit C<< is => 'bare' >> was passed
+to the attribute's constructor or that the attribute has at least one
+associated method (reader, writer, delegation, etc.).  Otherwise, it issues a
+warning.
+
 =item B<< $attr->handles >>
 
 This returns the value of the C<handles> option passed to the
index 5f722f1..0daeacb 100644 (file)
@@ -11,7 +11,7 @@ use List::Util qw( first );
 use List::MoreUtils qw( any all uniq first_index );
 use Scalar::Util 'weaken', 'blessed';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -243,11 +243,17 @@ sub superclasses {
 
 sub add_attribute {
     my $self = shift;
-    $self->SUPER::add_attribute(
+    my $attr =
         (blessed $_[0] && $_[0]->isa('Class::MOP::Attribute')
             ? $_[0]
-            : $self->_process_attribute(@_))
-    );
+            : $self->_process_attribute(@_));
+    $self->SUPER::add_attribute($attr);
+    # it may be a Class::MOP::Attribute, theoretically, which doesn't have
+    # 'bare' and doesn't implement this method
+    if ($attr->can('check_associated_methods')) {
+        $attr->check_associated_methods;
+    }
+    return $attr;
 }
 
 sub add_override_method_modifier {
index 40be9dd..1c283e7 100644 (file)
@@ -5,7 +5,7 @@ use warnings;
 
 use Class::MOP;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 6d6ac94..ad35595 100644 (file)
@@ -4,7 +4,7 @@ package Moose::Meta::Instance;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index c357454..bda1e34 100644 (file)
@@ -3,7 +3,7 @@ package Moose::Meta::Method;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 60db0e0..2a4b31d 100644 (file)
@@ -4,7 +4,7 @@ package Moose::Meta::Method::Accessor;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index e3aaab5..d5b9c7f 100644 (file)
@@ -3,7 +3,7 @@ package Moose::Meta::Method::Augmented;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 2977a82..a236208 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 
 use Scalar::Util 'blessed', 'weaken', 'looks_like_number', 'refaddr';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 our $AUTHORITY = 'cpan:STEVAN';
 
 use base 'Moose::Meta::Method',
index 205018c..5e64190 100644 (file)
@@ -7,7 +7,7 @@ use warnings;
 use Carp         'confess';
 use Scalar::Util 'blessed', 'weaken';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -79,7 +79,7 @@ sub _initialize_body {
     # NOTE: we used to do a goto here, but the goto didn't handle
     # failure correctly (it just returned nothing), so I took that
     # out. However, the more I thought about it, the less I liked it
-    # doing the goto, and I prefered the act of delegation being
+    # doing the goto, and I preferred the act of delegation being
     # actually represented in the stack trace.  - SL
     # not inlining this, since it won't really speed things up at
     # all... the only thing that would end up different would be
index a271b25..5fc20b0 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 
 use Scalar::Util 'blessed', 'weaken';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 1f782d0..223631e 100644 (file)
@@ -3,7 +3,7 @@ package Moose::Meta::Method::Overridden;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 4c77ee8..0da0ebc 100644 (file)
@@ -10,7 +10,7 @@ use Carp         'confess';
 use Sub::Name    'subname';
 use Devel::GlobalDestruction 'in_global_destruction';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -214,7 +214,8 @@ foreach my $modifier_type (qw[ before around after ]) {
     $META->add_method("get_${modifier_type}_method_modifiers" => sub {
         my ($self, $method_name) = @_;
         #return () unless exists $self->$attr_reader->{$method_name};
-        @{$self->$attr_reader->{$method_name}};
+        my $mm = $self->$attr_reader->{$method_name};
+        $mm ? @$mm : ();
     });
 
     $META->add_method("has_${modifier_type}_method_modifiers" => sub {
index 0685164..14ebcdd 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 use warnings;
 use metaclass;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 4184f1f..0c2f862 100644 (file)
@@ -8,7 +8,7 @@ use Scalar::Util 'blessed';
 
 use Moose::Meta::Role::Composite;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index b2f0d34..2a9ce8b 100644 (file)
@@ -7,7 +7,7 @@ use metaclass;
 use Moose::Util  'english_list';
 use Scalar::Util 'weaken', 'blessed';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 6331c63..3165f93 100644 (file)
@@ -6,7 +6,7 @@ use metaclass;
 
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 1b2edb6..1dafeca 100644 (file)
@@ -6,7 +6,7 @@ use metaclass;
 
 use Scalar::Util    'blessed';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 38be277..fad0671 100644 (file)
@@ -6,7 +6,7 @@ use metaclass;
 
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index db9a57e..56474a0 100644 (file)
@@ -4,7 +4,7 @@ package Moose::Meta::Role::Method;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 81a877f..5aea191 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 
 use base qw(Moose::Meta::Role::Method::Required);
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 401e6b6..184e3ea 100644 (file)
@@ -10,7 +10,7 @@ use overload '""'     => sub { shift->name },   # stringify to method name
 
 use base qw(Class::MOP::Object);
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index b7127d0..26340b1 100644 (file)
@@ -8,7 +8,7 @@ use metaclass;
 use Moose::Meta::Attribute;
 use Moose::Util::TypeConstraints ();
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index cd55f56..73e3c9f 100644 (file)
@@ -7,7 +7,7 @@ use metaclass;
 
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index bd5f2a9..e8f7943 100644 (file)
@@ -13,7 +13,7 @@ use Sub::Name qw(subname);
 
 use base qw(Class::MOP::Object);
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 410add7..bbd4c2e 100644 (file)
@@ -7,7 +7,7 @@ use metaclass;
 use Scalar::Util 'blessed';
 use Moose::Util::TypeConstraints ();
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index e2b1b05..6dfbc50 100644 (file)
@@ -9,7 +9,7 @@ use Moose::Util 'english_list';
 
 use Moose::Util::TypeConstraints ();
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index d6c0e1d..eb83bf0 100644 (file)
@@ -6,7 +6,7 @@ use metaclass;
 
 use Moose::Util::TypeConstraints ();
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index bfb2671..734c8cd 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 use warnings;
 use metaclass;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index b575e0b..613200d 100644 (file)
@@ -8,7 +8,7 @@ use Scalar::Util 'blessed';
 use Moose::Util::TypeConstraints;
 use Moose::Meta::TypeConstraint::Parameterizable;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 86432b5..ec1d0ed 100644 (file)
@@ -7,7 +7,7 @@ use metaclass;
 
 use Scalar::Util 'blessed';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 2ca0a5e..71c7d58 100644 (file)
@@ -7,7 +7,7 @@ use metaclass;
 use Scalar::Util 'blessed';
 use Moose::Util::TypeConstraints ();
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -20,7 +20,7 @@ __PACKAGE__->meta->add_attribute('role' => (
 sub new {
     my ( $class, %args ) = @_;
 
-    $args{parent} = Moose::Util::TypeConstraints::find_type_constraint('Role');
+    $args{parent} = Moose::Util::TypeConstraints::find_type_constraint('Object');
     my $self      = $class->_new(\%args);
 
     $self->_create_hand_optimized_type_constraint;
index e6216bc..be5e4f9 100644 (file)
@@ -7,7 +7,7 @@ use metaclass;
 
 use Moose::Meta::TypeCoercion::Union;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index e823e21..4d395b3 100644 (file)
@@ -11,7 +11,7 @@ use Scalar::Util;
 use if ( not our $__mx_is_compiled ), 'Moose::Meta::Class';
 use if ( not our $__mx_is_compiled ), metaclass => 'Moose::Meta::Class';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index d7e71d5..687d32c 100644 (file)
@@ -6,7 +6,7 @@ use Carp         'croak';
 
 use Sub::Exporter;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -41,7 +41,7 @@ sub has {
     my $meta = Moose::Meta::Role->initialize(shift);
     my $name = shift;
     croak 'Usage: has \'name\' => ( key => value, ... )' if @_ == 1;
-    my %options = @_;
+    my %options = ( definition_context => Moose::Util::_caller_info(), @_ );
     my $attrs = ( ref($name) eq 'ARRAY' ) ? $name : [ ($name) ];
     $meta->add_attribute( $_, %options ) for @$attrs;
 }
index d4c0d93..36fdf58 100644 (file)
@@ -8,7 +8,7 @@ use Sub::Exporter;
 use Scalar::Util 'blessed';
 use Class::MOP   0.60;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -207,6 +207,13 @@ sub english_list {
     return $list;
 }
 
+sub _caller_info {
+    my $level = @_ ? ($_[0] + 1) : 2;
+    my %info;
+    @info{qw(package file line)} = caller($level);
+    return \%info;
+}
+
 1;
 
 __END__
index da50bf7..808fbf7 100644 (file)
@@ -3,7 +3,7 @@ package Moose::Util::MetaRole;
 use strict;
 use warnings;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index 7d7da3a..4155b0a 100644 (file)
@@ -6,7 +6,7 @@ use List::MoreUtils qw( all any );
 use Scalar::Util qw( blessed reftype );
 use Moose::Exporter;
 
-our $VERSION = '0.83';
+our $VERSION = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -657,6 +657,7 @@ subtype 'Object' => as 'Ref' =>
     where { blessed($_) && blessed($_) ne 'Regexp' } =>
     optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Object;
 
+# This type is deprecated.
 subtype 'Role' => as 'Object' => where { $_->can('does') } =>
     optimize_as \&Moose::Util::TypeConstraints::OptimizedConstraints::Role;
 
@@ -848,10 +849,10 @@ that hierarchy represented visually.
       Defined
           Value
               Num
-                Int
+                  Int
               Str
-                ClassName
-                RoleName
+                  ClassName
+                  RoleName
           Ref
               ScalarRef
               ArrayRef[`a]
@@ -859,9 +860,8 @@ that hierarchy represented visually.
               CodeRef
               RegexpRef
               GlobRef
-                FileHandle
+                  FileHandle
               Object
-                Role
 
 B<NOTE:> Any type followed by a type parameter C<[`a]> can be
 parameterized, this means you can say:
@@ -887,8 +887,7 @@ existence check. This means that your class B<must> be loaded for this
 type constraint to pass.
 
 B<NOTE:> The C<RoleName> constraint checks a string is a I<package
-name> which is a role, like C<'MyApp::Role::Comparable'>. The C<Role>
-constraint checks that an I<object does> the named role.
+name> which is a role, like C<'MyApp::Role::Comparable'>.
 
 =head2 Type Constraint Naming
 
index 461f53d..6168558 100644 (file)
@@ -6,7 +6,7 @@ use warnings;
 use Class::MOP;
 use Scalar::Util 'blessed', 'looks_like_number';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
@@ -31,7 +31,7 @@ sub FileHandle { ref($_[0]) eq 'GLOB' && Scalar::Util::openhandle($_[0]) or bles
 
 sub Object { blessed($_[0]) && blessed($_[0]) ne 'Regexp' }
 
-sub Role { blessed($_[0]) && $_[0]->can('does') }
+sub Role { Carp::cluck('The Role type is deprecated.'); blessed($_[0]) && $_[0]->can('does') }
 
 sub ClassName {
     return Class::MOP::is_class_loaded( $_[0] );
index 42dc3f3..9f76409 100644 (file)
@@ -8,7 +8,7 @@ use Test::Builder;
 
 use Moose::Util 'does_role', 'find_meta';
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
index f483295..be7797d 100644 (file)
@@ -5,7 +5,7 @@ use warnings;
 
 use Class::MOP;
 
-our $VERSION   = '0.83';
+our $VERSION   = '0.84';
 $VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
diff --git a/t/010_basics/022_moose_exporter_groups.t b/t/010_basics/022_moose_exporter_groups.t
new file mode 100755 (executable)
index 0000000..11b901f
--- /dev/null
@@ -0,0 +1,166 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 45;
+use Test::Exception;
+
+{
+    package ExGroups1;
+    use Moose::Exporter;
+    use Moose ();
+
+    Moose::Exporter->setup_import_methods(
+        also        => ['Moose'],
+        with_meta   => ['with_meta1'],
+        with_caller => ['default_export1'],
+        as_is       => ['default_export2'],
+        groups      => { all_group  => [':all'], 
+                         just_one   => ['default_export1'] }
+    );
+
+    sub default_export1 { 1 }
+    sub default_export2 { 2 }
+
+    sub with_meta1 (&) {
+        my ($meta, $code) = @_;
+        return $meta;
+    }
+}
+
+{
+    package UseAllGroup;
+    
+    ExGroups1->import(':all_group');
+
+    ::can_ok( __PACKAGE__, 'with_meta1' );
+    ::can_ok( __PACKAGE__, 'default_export1' );
+    ::can_ok( __PACKAGE__, 'default_export2' );
+    ::can_ok( __PACKAGE__, 'has' );
+
+    my $meta;
+    eval q/$meta = with_meta1 { return 'coderef'; }/;
+    ::is($@, '', 'calling with_meta1 with prototype is not an error');
+    ::isa_ok( $meta, 'Moose::Meta::Class', 'with_meta first argument' );
+    ::is( prototype( __PACKAGE__->can('with_meta1') ), 
+          prototype( ExGroups1->can('with_meta1') ),
+    'using correct prototype on with_meta function' );
+
+    ExGroups1->unimport();
+
+    ::ok( ! __PACKAGE__->can('with_meta1'), __PACKAGE__.'::with_meta1() has been cleaned' );
+    ::ok( ! __PACKAGE__->can('default_export1'), __PACKAGE__.'::default_export1() has been cleaned' );
+    ::ok( ! __PACKAGE__->can('default_export2'), __PACKAGE__.'::default_export2() has been cleaned' );
+    ::ok( ! __PACKAGE__->can('has'), __PACKAGE__.'::has() has been cleaned' );
+}
+
+{
+    package UseJustOne;
+
+    ExGroups1->import(':just_one');
+
+    ::can_ok( __PACKAGE__, 'default_export1' );
+    ::ok( ! __PACKAGE__->can('default_export2'), __PACKAGE__.'::default_export2() was not imported' );
+    ::ok( ! __PACKAGE__->can('has'), __PACKAGE__.'::has() was not imported' );
+
+    ExGroups1->unimport();
+
+    ::ok( ! __PACKAGE__->can('default_export1'), __PACKAGE__.'::default_export1() has been cleared' );
+}
+
+{
+    package ExGroups2;
+    use Moose::Exporter;
+    
+    Moose::Exporter->setup_import_methods(
+        also        => ['ExGroups1'],
+        as_is       => ['exgroups2_as_is'],
+        with_caller => ['exgroups2_with_caller'],
+        groups      => { default    => ['exgroups2_as_is'],
+                         code_group => \&generate_group,
+                         parent1    => [qw(:ExGroups1 :code_group)],
+                         parent2    => [qw(:all)] }
+    );
+
+    sub exgroups2_as_is { 3 }
+
+    sub generate_group {
+        my ($caller, $group_name, $args, $context) = @_;
+
+        ::is($group_name, 'code_group', 'original name is passed to group code');
+        ::is($args->{install_as}, $caller . '_code', 'group code arguments match caller');
+        ::is($context->{from}, __PACKAGE__, 'defined package name is passed to group code');
+
+        return { $args->{install_as} => \&exported_by_group };
+    }
+
+    sub exported_by_group (&) {
+        my ($caller, $coderef) = @_;
+        return $caller;
+    }
+}
+
+{
+    package UseDefault;
+    
+    ExGroups2->import;
+
+    ::can_ok( __PACKAGE__, 'exgroups2_as_is' );
+    ::ok( ! __PACKAGE__->can('exgroups2_with_caller'), '"default" group is no longer "all"' );
+}
+
+{
+    package UseCodeGroup;
+
+    ExGroups2->import(':code_group', { install_as => (my $export_name = __PACKAGE__.'_code') });
+
+    ::can_ok( __PACKAGE__, $export_name );
+    ::ok( &UseCodeGroup_code() eq __PACKAGE__, 'code group exports act like "with_caller" subs' );
+    ::lives_ok(sub { UseCodeCodeGroup_code { return 'code block'; } }, 'code group exports keep their prototypes');
+
+    ::ok( ! __PACKAGE__->can('exgroups2_as_is'), 'code group will not automatically export any symbols' );
+
+    ExGroups2->unimport;
+    
+    ::ok( ! __PACKAGE__->can($export_name), 
+        'dynamically-named '. __PACKAGE__."::$export_name() has been cleared" );
+}
+
+{
+    package UseParent1;
+
+    ExGroups2->import(':parent1', { install_as => (my $export_name = __PACKAGE__.'_code') });
+
+    ::can_ok( __PACKAGE__, $export_name );
+    ::can_ok( __PACKAGE__, 'default_export1' );
+    ::can_ok( __PACKAGE__, 'default_export2' );
+    ::can_ok( __PACKAGE__, 'has' );
+
+    ExGroups2->unimport;
+
+    ::ok( ! __PACKAGE__->can($export_name), __PACKAGE__."::$export_name() has been cleared" );
+    ::ok( ! __PACKAGE__->can('default_export1'), __PACKAGE__.'::default_export1() has been cleaned' );
+    ::ok( ! __PACKAGE__->can('default_export2'), __PACKAGE__.'::default_export2() has been cleaned' );
+    ::ok( ! __PACKAGE__->can('has'), __PACKAGE__.'::has() has been cleaned' );
+}
+
+{
+    package UseParent2;
+
+    ExGroups2->import(':parent2', { install_as => (my $export_name = __PACKAGE__.'_code') });
+
+    ::ok( ! __PACKAGE__->can($export_name), '"all" group will not call code groups' );
+    ::can_ok( __PACKAGE__, 'exgroups2_as_is' );
+    ::can_ok( __PACKAGE__, 'exgroups2_with_caller' );
+    ::can_ok( __PACKAGE__, 'default_export1' );
+    ::can_ok( __PACKAGE__, 'has' );
+
+    ExGroups2->unimport;
+
+    ::ok( ! __PACKAGE__->can('exgroups2_as_is'), __PACKAGE__.'::exgroups2_as_is() has been cleaned' );
+    ::ok( ! __PACKAGE__->can('exgroups2_with_caller'), __PACKAGE__.'::exgroups2_with_caller() has been cleaned' );
+    ::ok( ! __PACKAGE__->can('default_export1'), __PACKAGE__.'::default_export1() has been cleaned' );
+    ::ok( ! __PACKAGE__->can('has'), __PACKAGE__.'::has() has been cleaned' );
+}
+
index 6f6a9f2..d6a4183 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 13;
+use Test::More tests => 14;
 use Test::Exception;
 
 
@@ -27,6 +27,16 @@ use Test::Exception;
         );
     };
     ::ok(!$@, '... created the lazy reader method okay') or warn $@;
+
+    my $warn;
+
+    eval {
+        local $SIG{__WARN__} = sub { $warn = $_[0] };
+        has 'mtfnpy' => (
+            reder => 'get_mftnpy'
+        );
+    };
+    ::ok($warn, '... got a warning for mispelled attribute argument');
 }
 
 {
index 01145f8..b0ef886 100644 (file)
@@ -19,7 +19,7 @@ use Test::Exception;
     has 'bar' => (is => 'rw', does => 'Bar::Role');
     has 'baz' => (
         is   => 'rw',
-        does => subtype('Role', where { $_->does('Bar::Role') })
+        does => role_type('Bar::Role')
     );
 
     package Bar::Role;
index 5f0ba66..e932718 100644 (file)
@@ -8,13 +8,13 @@ use Test::More tests => 2;
 use Moose ();
 use Moose::Meta::Class;
 
-my $meta = Moose::Meta::Class->create_anon_class;
+my $meta = Moose::Meta::Class->create('Banana');
 
 my $warn;
 $SIG{__WARN__} = sub { $warn = "@_" };
 
 $meta->add_attribute('foo');
-like $warn, qr/Attribute \(foo\) has no associated methods/,
+like $warn, qr/Attribute \(foo\) of class Banana has no associated methods/,
   'correct error message';
 
 $warn = '';
diff --git a/t/020_attributes/027_accessor_override_method.t b/t/020_attributes/027_accessor_override_method.t
new file mode 100644 (file)
index 0000000..22f562a
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More;
+
+BEGIN {
+    eval "use Test::Output;";
+    plan skip_all => "Test::Output is required for this test" if $@;
+    plan tests => 5;
+}
+
+{
+    package Foo;
+    use Moose;
+
+    sub get_a { }
+    sub set_b { }
+    sub has_c { }
+    sub clear_d { }
+    sub e { }
+}
+
+my $foo_meta = Foo->meta;
+stderr_like(sub { $foo_meta->add_attribute(a => (reader => 'get_a')) },
+            qr/^You cannot overwrite a locally defined method \(get_a\) with an accessor/, 'reader overriding gives proper warning');
+stderr_like(sub { $foo_meta->add_attribute(b => (writer => 'set_b')) },
+            qr/^You cannot overwrite a locally defined method \(set_b\) with an accessor/, 'writer overriding gives proper warning');
+stderr_like(sub { $foo_meta->add_attribute(c => (predicate => 'has_c')) },
+            qr/^You cannot overwrite a locally defined method \(has_c\) with an accessor/, 'predicate overriding gives proper warning');
+stderr_like(sub { $foo_meta->add_attribute(d => (clearer => 'clear_d')) },
+            qr/^You cannot overwrite a locally defined method \(clear_d\) with an accessor/, 'clearer overriding gives proper warning');
+stderr_like(sub { $foo_meta->add_attribute(e => (is => 'rw')) },
+            qr/^You cannot overwrite a locally defined method \(e\) with an accessor/, 'accessor overriding gives proper warning');
index 1bb4741..70c31a2 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 36;
+use Test::More tests => 41;
 use Test::Exception;
 
 =pod
@@ -81,17 +81,25 @@ is_deeply(
 
 ok($foo_role->has_attribute('bar'), '... FooRole does have the bar attribute');
 
-is_deeply(
-    $foo_role->get_attribute('bar'),
-    { is => 'rw', isa => 'Foo' },
-    '... got the correct description of the bar attribute');
+my $bar_attr = $foo_role->get_attribute('bar');
+is($bar_attr->{is}, 'rw',
+   'bar attribute is rw');
+is($bar_attr->{isa}, 'Foo',
+   'bar attribute isa Foo');
+is(ref($bar_attr->{definition_context}), 'HASH',
+   'bar\'s definition context is a hash');
+is($bar_attr->{definition_context}->{package}, 'FooRole',
+   'bar was defined in FooRole');
 
 ok($foo_role->has_attribute('baz'), '... FooRole does have the baz attribute');
 
-is_deeply(
-    $foo_role->get_attribute('baz'),
-    { is => 'ro' },
-    '... got the correct description of the baz attribute');
+my $baz_attr = $foo_role->get_attribute('baz');
+is($baz_attr->{is}, 'ro',
+   'baz attribute is ro');
+is(ref($baz_attr->{definition_context}), 'HASH',
+   'bar\'s definition context is a hash');
+is($baz_attr->{definition_context}->{package}, 'FooRole',
+   'baz was defined in FooRole');
 
 # method modifiers
 
diff --git a/t/030_roles/041_empty_method_modifiers_meta_bug.t b/t/030_roles/041_empty_method_modifiers_meta_bug.t
new file mode 100644 (file)
index 0000000..e7a0f9f
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+
+use Test::More tests => 6;
+
+# test role and class
+package SomeRole;
+use Moose::Role;
+
+requires 'foo';
+
+package SomeClass;
+use Moose;
+has 'foo' => (is => 'rw');
+with 'SomeRole';
+
+package main;
+
+#my $c = SomeClass->new;
+#isa_ok( $c, 'SomeClass');
+
+for my $modifier_type (qw[ before around after ]) {
+    my $get_func = "get_${modifier_type}_method_modifiers";
+    my @mms = eval{ SomeRole->meta->$get_func('foo') };
+    is($@, '', "$get_func for no method mods does not die");
+    is(scalar(@mms),0,'is an empty list');
+}
index 2457d50..bb1ded0 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 291;
+use Test::More tests => 277;
 use Test::Exception;
 
 use Scalar::Util ();
@@ -283,26 +283,6 @@ ok(!defined Object(qr/../),           '... Object rejects anything which is not
 ok(defined Object(bless {}, 'Foo'),   '... Object accepts anything which is blessed');
 ok(!defined Object(undef),             '... Object accepts anything which is blessed');
 
-{
-    package My::Role;
-    sub does { 'fake' }
-}
-
-ok(!defined Role(0),                    '... Role rejects anything which is not a Role');
-ok(!defined Role(100),                  '... Role rejects anything which is not a Role');
-ok(!defined Role(''),                   '... Role rejects anything which is not a Role');
-ok(!defined Role('Foo'),                '... Role rejects anything which is not a Role');
-ok(!defined Role([]),                   '... Role rejects anything which is not a Role');
-ok(!defined Role({}),                   '... Role rejects anything which is not a Role');
-ok(!defined Role(sub {}),               '... Role rejects anything which is not a Role');
-ok(!defined Role($SCALAR_REF),          '... Role rejects anything which is not a Role');
-ok(!defined Role($GLOB_REF),            '... Role rejects anything which is not a Role');
-ok(!defined Role($fh),                  '... Role rejects anything which is not a Role');
-ok(!defined Role(qr/../),               '... Role rejects anything which is not a Role');
-ok(!defined Role(bless {}, 'Foo'),      '... Role rejects anything which is not a Role');
-ok(defined Role(bless {}, 'My::Role'),  '... Role accepts anything which is a Role');
-ok(!defined Role(undef),                '... Role rejects anything which is not a Role');
-
 ok(!defined ClassName(0),               '... ClassName rejects anything which is not a ClassName');
 ok(!defined ClassName(100),             '... ClassName rejects anything which is not a ClassName');
 ok(!defined ClassName(''),              '... ClassName rejects anything which is not a ClassName');
index f20f68d..6273f54 100644 (file)
@@ -3,7 +3,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 19;
+use Test::More tests => 18;
 use Test::Exception;
 
 BEGIN {
@@ -44,7 +44,6 @@ ok( $type->is_subtype_of("Gorch"), "subtype of gorch" );
 ok( $type->is_subtype_of("Bar"), "subtype of bar" );
 
 ok( $type->is_subtype_of("Object"), "subtype of Object" );
-ok( $type->is_subtype_of("Role"), "subtype of Role" );
 
 ok( !$type->is_subtype_of("ThisTypeDoesNotExist"), "not subtype of unknown type name" );
 ok( !$type->is_a_type_of("ThisTypeDoesNotExist"), "not type of unknown type name" );
index f5d36ff..7988805 100644 (file)
@@ -79,6 +79,7 @@ my %trustme = (
     'Moose::Meta::TypeConstraint::Class' =>
         [qw( equals is_a_type_of is_a_subtype_of )],
     'Moose::Meta::TypeConstraint::Enum' => [qw( constraint equals )],
+    'Moose::Meta::TypeConstraint::DuckType' => [qw( constraint equals get_message )],
     'Moose::Meta::TypeConstraint::Parameterizable' => ['.+'],
     'Moose::Meta::TypeConstraint::Parameterized'   => ['.+'],
     'Moose::Meta::TypeConstraint::Role'  => [qw( equals is_a_type_of )],
index c5b9f17..5851ce3 100644 (file)
@@ -124,6 +124,7 @@ destructor
 destructors
 dev
 DWIM
+DUCKTYPE
 hashrefs
 hotspots
 immutabilize