bump version to 0.65 and update changes for stable release
[gitmo/Class-MOP.git] / lib / Class / MOP.pm
index 6148129..c1f7642 100644 (file)
@@ -4,13 +4,13 @@ package Class::MOP;
 use strict;
 use warnings;
 
+use 5.008;
+
 use MRO::Compat;
 
 use Carp          'confess';
 use Scalar::Util  'weaken';
 
-use Sub::Identify 'get_code_info';
-
 BEGIN {
     local $@;
     eval {
@@ -26,7 +26,7 @@ BEGIN {
         require Devel::GlobalDestruction;
         Devel::GlobalDestruction->import("in_global_destruction");
         1;
-    } or *in_global_destruction = sub () { '' };
+    } or *in_global_destruction = sub () { !1 };
 }
 
 
@@ -47,23 +47,40 @@ BEGIN {
 }
 
 our $VERSION   = '0.65';
+our $XS_VERSION = $VERSION;
+$VERSION = eval $VERSION;
 our $AUTHORITY = 'cpan:STEVAN';    
     
 # after that everything is loaded, if we're allowed try to load faster XS
 # versions of various things
-unless ($ENV{CLASS_MOP_NO_XS}) {
+_try_load_xs() or _load_pure_perl();
+
+sub _try_load_xs {
+    return if $ENV{CLASS_MOP_NO_XS};
+
     my $e = do {
         local $@;
         eval {
             require XSLoader;
-            __PACKAGE__->XSLoader::load($VERSION);
+            # just doing this - no warnings 'redefine' - doesn't work
+            # for some reason
+            local $^W = 0;
+            __PACKAGE__->XSLoader::load($XS_VERSION);
         };
         $@;
     };
 
     die $e if $e && $e !~ /object version|loadable object/;
+
+    return $e ? 0 : 1;
+}
+
+sub _load_pure_perl {
+    require Sub::Identify;
+    Sub::Identify->import('get_code_info');
 }
 
+
 {
     # Metaclasses are singletons, so we cache them here.
     # there is no need to worry about destruction though
@@ -92,7 +109,7 @@ unless ($ENV{CLASS_MOP_NO_XS}) {
 sub load_class {
     my $class = shift;
 
-    if (ref($class) || !defined($class) || !length($class)) {
+    unless ( _is_valid_class_name($class) ) {
         my $display = defined($class) ? $class : 'undef';
         confess "Invalid class name ($display)";
     }
@@ -100,9 +117,7 @@ sub load_class {
     # if the class is not already loaded in the symbol table..
     unless (is_class_loaded($class)) {
         # require it
-        my $file = $class . '.pm';
-        $file =~ s{::}{/}g;
-        my $e = do { local $@; eval { require($file) }; $@ };
+        my $e = do { local $@; eval "require $class"; $@ };
         confess "Could not load class ($class) because : $e" if $e;
     }
 
@@ -115,6 +130,18 @@ sub load_class {
     return get_metaclass_by_name($class) if defined wantarray;
 }
 
+sub _is_valid_class_name {
+    my $class = shift;
+
+    return 0 if ref($class);
+    return 0 unless defined($class);
+    return 0 unless length($class);
+
+    return 1 if $class =~ /^\w+(?:::\w+)*$/;
+
+    return 0;
+}
+
 sub is_class_loaded {
     my $class = shift;
 
@@ -208,15 +235,6 @@ Class::MOP::Package->meta->add_attribute(
     ))
 );
 
-# NOTE:
-# use the metaclass to construct the meta-package
-# which is a superclass of the metaclass itself :P
-Class::MOP::Package->meta->add_method('initialize' => sub {
-    my $class        = shift;
-    my $package_name = shift;
-    $class->meta->new_object('package' => $package_name, @_);
-});
-
 ## --------------------------------------------------------
 ## Class::MOP::Module
 
@@ -451,40 +469,6 @@ Class::MOP::Attribute->meta->add_attribute(
     ))
 );
 
-# NOTE: (meta-circularity)
-# This should be one of the last things done
-# it will "tie the knot" with Class::MOP::Attribute
-# so that it uses the attributes meta-objects
-# to construct itself.
-Class::MOP::Attribute->meta->add_method('new' => sub {
-    my ( $class, @args ) = @_;
-
-    unshift @args, "name" if @args % 2 == 1;
-    my %options = @args;
-
-    my $name = $options{name};
-
-    (defined $name && $name)
-        || confess "You must provide a name for the attribute";
-    $options{init_arg} = $name
-        if not exists $options{init_arg};
-
-    if(exists $options{builder}){
-        confess("builder must be a defined scalar value which is a method name")
-            if ref $options{builder} || !(defined $options{builder});
-        confess("Setting both default and builder is not allowed.")
-            if exists $options{default};
-    } else {
-        (Class::MOP::Attribute::is_default_a_coderef(\%options))
-            || confess("References are not allowed as default values, you must ".
-                       "wrap the default of '$name' in a CODE reference (ex: sub { [] } and not [])")
-                if exists $options{default} && ref $options{default};
-    }
-
-    # return the new object
-    $class->meta->new_object(%options);
-});
-
 Class::MOP::Attribute->meta->add_method('clone' => sub {
     my $self  = shift;
     $self->meta->clone_object($self, @_);
@@ -516,25 +500,6 @@ Class::MOP::Method->meta->add_attribute(
     ))
 );
 
-# FIMXE prime candidate for immutablization
-Class::MOP::Method->meta->add_method('wrap' => sub {
-    my ( $class, @args ) = @_;
-
-    unshift @args, 'body' if @args % 2 == 1;
-
-    my %options = @args;
-    my $code = $options{body};
-
-    ('CODE' eq ref($code))
-        || confess "You must supply a CODE reference to bless, not (" . ($code || 'undef') . ")";
-
-    ($options{package_name} && $options{name})
-        || confess "You must supply the package_name and name parameters";
-
-    # return the new object
-    $class->meta->new_object(%options);
-});
-
 Class::MOP::Method->meta->add_method('clone' => sub {
     my $self  = shift;
     $self->meta->clone_object($self, @_);
@@ -562,15 +527,6 @@ Class::MOP::Method::Generated->meta->add_attribute(
     ))
 );
 
-Class::MOP::Method::Generated->meta->add_method('new' => sub {
-    my ($class, %options) = @_;
-    ($options{package_name} && $options{name})
-        || confess "You must supply the package_name and name parameters";    
-    my $self = $class->meta->new_object(%options);
-    $self->initialize_body;  
-    $self;
-});
-
 ## --------------------------------------------------------
 ## Class::MOP::Method::Accessor
 
@@ -588,36 +544,6 @@ Class::MOP::Method::Accessor->meta->add_attribute(
     ))
 );
 
-Class::MOP::Method::Accessor->meta->add_method('new' => sub {
-    my $class   = shift;
-    my %options = @_;
-
-    (exists $options{attribute})
-        || confess "You must supply an attribute to construct with";
-
-    (exists $options{accessor_type})
-        || confess "You must supply an accessor_type to construct with";
-
-    (Scalar::Util::blessed($options{attribute}) && $options{attribute}->isa('Class::MOP::Attribute'))
-        || confess "You must supply an attribute which is a 'Class::MOP::Attribute' instance";
-
-    ($options{package_name} && $options{name})
-        || confess "You must supply the package_name and name parameters";
-
-    # return the new object
-    my $self = $class->meta->new_object(%options);
-    
-    # we don't want this creating
-    # a cycle in the code, if not
-    # needed
-    Scalar::Util::weaken($self->{'attribute'});
-
-    $self->initialize_body;  
-    
-    $self;
-});
-
-
 ## --------------------------------------------------------
 ## Class::MOP::Method::Constructor
 
@@ -639,30 +565,6 @@ Class::MOP::Method::Constructor->meta->add_attribute(
     ))
 );
 
-Class::MOP::Method::Constructor->meta->add_method('new' => sub {
-    my $class   = shift;
-    my %options = @_;
-
-    (Scalar::Util::blessed $options{metaclass} && $options{metaclass}->isa('Class::MOP::Class'))
-        || confess "You must pass a metaclass instance if you want to inline"
-            if $options{is_inline};
-
-    ($options{package_name} && $options{name})
-        || confess "You must supply the package_name and name parameters";
-
-    # return the new object
-    my $self = $class->meta->new_object(%options);
-    
-    # we don't want this creating
-    # a cycle in the code, if not
-    # needed
-    Scalar::Util::weaken($self->{'associated_metaclass'});
-
-    $self->initialize_body;  
-    
-    $self;
-});
-
 ## --------------------------------------------------------
 ## Class::MOP::Instance
 
@@ -687,7 +589,7 @@ Class::MOP::Instance->meta->add_attribute(
 
 Class::MOP::Instance->meta->add_attribute(
     Class::MOP::Attribute->new('attributes',
-        reader   => { attributes => \&Class::MOP::Instance::attributes },
+        reader   => { attributes => \&Class::MOP::Instance::get_all_attributes },
     ),
 );
 
@@ -708,17 +610,6 @@ Class::MOP::Instance->meta->add_attribute(
 # for the constructor to be able to use it
 Class::MOP::Instance->meta->get_meta_instance;
 
-Class::MOP::Instance->meta->add_method('new' => sub {
-    my $class   = shift;
-    my $options = $class->BUILDARGS(@_);
-
-    my $self = $class->meta->new_object(%$options);
-    
-    Scalar::Util::weaken($self->{'associated_metaclass'});
-
-    $self;
-});
-
 # pretend the add_method never happenned. it hasn't yet affected anything
 undef Class::MOP::Instance->meta->{_package_cache_flag};
 
@@ -733,8 +624,10 @@ undef Class::MOP::Instance->meta->{_package_cache_flag};
 # no actual benefits.
 
 $_->meta->make_immutable(
-    inline_constructor => 0,
-    inline_accessors   => 0,
+    inline_constructor  => 1,
+    replace_constructor => 1,
+    constructor_name    => "_new",
+    inline_accessors => 0,
 ) for qw/
     Class::MOP::Package
     Class::MOP::Module
@@ -998,6 +891,13 @@ If possible, we will load the L<Sub::Name> module and this will function
 as C<Sub::Name::subname> does, otherwise it will just return the C<$code>
 argument.
 
+=item B<in_global_destruction>
+
+If L<Devel::GlobalDestruction> is available, this returns true under global
+destruction.
+
+Otherwise it's a constant returning false.
+
 =back
 
 =head2 Metaclass cache functions