Apply changes to deprecate alias_method previously applied on trunk
[gitmo/Class-MOP.git] / lib / Class / MOP / Class.pm
index 83088da..c8962f2 100644 (file)
@@ -12,6 +12,7 @@ use Carp         'confess';
 use Scalar::Util 'blessed', 'weaken';
 
 our $VERSION   = '0.65';
+$VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';
 
 use base 'Class::MOP::Module';
@@ -168,9 +169,9 @@ sub check_metaclass_compatability {
         # we also need to check that instance metaclasses
         # are compatabile in the same the class.
         ($self->instance_metaclass->isa($meta->instance_metaclass))
-            || confess $self->name . "->meta => (" . ($self->instance_metaclass) . ")" .
+            || confess $self->name . "->meta->instance_metaclass => (" . ($self->instance_metaclass) . ")" .
                        " is not compatible with the " .
-                       $class_name . "->meta => (" . ($meta->instance_metaclass) . ")";
+                       $class_name . "->meta->instance_metaclass => (" . ($meta->instance_metaclass) . ")";
     }
 }
 
@@ -211,7 +212,7 @@ sub check_metaclass_compatability {
     sub DESTROY {
         my $self = shift;
 
-        return if Class::MOP::in_global_destruction; # it'll happen soon anyway and this just makes things more complicated
+        return if Class::MOP::in_global_destruction(); # it'll happen soon anyway and this just makes things more complicated
 
         no warnings 'uninitialized';
         return unless $self->name =~ /^$ANON_CLASS_PREFIX/;
@@ -587,6 +588,20 @@ sub class_precedence_list {
 
 ## Methods
 
+sub wrap_method_body {
+    my ( $self, %args ) = @_;
+
+    my $body = delete $args{body}; # delete is for compat
+
+    ('CODE' eq ref($body))
+        || confess "Your code block must be a CODE reference";
+
+    $self->method_metaclass->wrap( $body => (
+        package_name => $self->name,
+        %args,
+    ));
+}
+
 sub add_method {
     my ($self, $method_name, $method) = @_;
     (defined $method_name && $method_name)
@@ -608,14 +623,7 @@ sub add_method {
     }
     else {
         $body = $method;
-        ('CODE' eq ref($body))
-            || confess "Your code block must be a CODE reference";
-        $method = $self->method_metaclass->wrap(
-            $body => (
-                package_name => $self->name,
-                name         => $method_name
-            )
-        );
+        $method = $self->wrap_method_body( body => $body, name => $method_name );
     }
 
     $method->attach_to_class($self);
@@ -702,17 +710,9 @@ sub add_method {
 }
 
 sub alias_method {
-    my ($self, $method_name, $method) = @_;
-    (defined $method_name && $method_name)
-        || confess "You must define a method name";
-
-    my $body = (blessed($method) ? $method->body : $method);
-    ('CODE' eq ref($body))
-        || confess "Your code block must be a CODE reference";
+    my $self = shift;
 
-    $self->add_package_symbol(
-        { sigil => '&', type => 'CODE', name => $method_name } => $body
-    );
+    $self->add_method(@_);
 }
 
 sub has_method {
@@ -720,8 +720,7 @@ sub has_method {
     (defined $method_name && $method_name)
         || confess "You must define a method name";
 
-    return 0 unless exists $self->get_method_map->{$method_name};
-    return 1;
+    exists $self->get_method_map->{$method_name};
 }
 
 sub get_method {
@@ -980,6 +979,25 @@ sub find_attribute_by_name {
     return;
 }
 
+# check if we can reinitialize
+sub is_pristine {
+    my $self = shift;
+
+    # if any local attr is defined
+    return if $self->get_attribute_list;
+
+    # or any non-declared methods
+    if ( my @methods = values %{ $self->get_method_map } ) {
+        my $metaclass = $self->method_metaclass;
+        foreach my $method ( @methods ) {
+            return if $method->isa("Class::MOP::Method::Generated");
+            # FIXME do we need to enforce this too? return unless $method->isa($metaclass);
+        }
+    }
+
+    return 1;
+}
+
 ## Class closing
 
 sub is_mutable   { 1 }
@@ -1071,7 +1089,9 @@ sub create_immutable_transformer {
         /],
         memoize     => {
            class_precedence_list             => 'ARRAY',
-           linearized_isa                    => 'ARRAY',
+           linearized_isa                    => 'ARRAY', # FIXME perl 5.10 memoizes this on its own, no need?
+           get_all_methods                   => 'ARRAY',
+           #get_all_attributes               => 'ARRAY', # it's an alias, no need, but maybe in the future
            compute_all_applicable_attributes => 'ARRAY',
            get_meta_instance                 => 'SCALAR',
            get_method_map                    => 'SCALAR',
@@ -1085,7 +1105,12 @@ sub create_immutable_transformer {
                 my $original = shift;
                 confess "Cannot add package symbols to an immutable metaclass" 
                     unless (caller(2))[3] eq 'Class::MOP::Package::get_package_symbol'; 
-                goto $original->body;
+
+                # This is a workaround for a bug in 5.8.1 which thinks that
+                # goto $original->body
+                # is trying to go to a label
+                my $body = $original->body;
+                goto $body;
             },
         },
     });
@@ -1375,6 +1400,11 @@ This returns true if the class is still mutable.
 
 This returns true if the class has been made immutable.
 
+=item B<is_pristine>
+
+Checks whether the class has any data that will be lost if C<reinitialize> is
+called.
+
 =back
 
 =head2 Inheritance Relationships
@@ -1417,10 +1447,19 @@ Returns a HASH ref of name to CODE reference mapping for this class.
 Returns the class name of the method metaclass, see L<Class::MOP::Method> 
 for more information on the method metaclasses.
 
-=item B<add_method ($method_name, $method)>
+=item B<wrap_method_body(%attrs)>
+
+Wrap a code ref (C<$attrs{body>) with C<method_metaclass>.
 
-This will take a C<$method_name> and CODE reference to that
-C<$method> and install it into the class's package.
+=item B<add_method ($method_name, $method, %attrs)>
+
+This will take a C<$method_name> and CODE reference or meta method
+objectand install it into the class's package.
+
+You are strongly encouraged to pass a meta method object instead of a
+code reference. If you do so, that object gets stored as part of the
+class's method map, providing more useful information about the method
+for introspection.
 
 B<NOTE>:
 This does absolutely nothing special to C<$method>
@@ -1428,16 +1467,6 @@ other than use B<Sub::Name> to make sure it is tagged with the
 correct name, and therefore show up correctly in stack traces and
 such.
 
-=item B<alias_method ($method_name, $method)>
-
-This will take a C<$method_name> and CODE reference to that
-C<$method> and alias the method into the class's package.
-
-B<NOTE>:
-Unlike C<add_method>, this will B<not> try to name the
-C<$method> using B<Sub::Name>, it only aliases the method in
-the class's package.
-
 =item B<has_method ($method_name)>
 
 This just provides a simple way to check if the class implements
@@ -1525,6 +1554,11 @@ This will return the first method to match a given C<$method_name> in
 the superclasses, this is basically equivalent to calling
 C<SUPER::$method_name>, but it can be dispatched at runtime.
 
+=item B<alias_method ($method_name, $method)>
+
+B<NOTE>: This method is now deprecated. Just use C<add_method>
+instead.
+
 =back
 
 =head2 Method Modifiers