Some errors for auto_deref
[gitmo/Mouse.git] / lib / Mouse.pm
index 1c06330..58637af 100644 (file)
@@ -9,16 +9,17 @@ use Sub::Exporter;
 use Carp 'confess';
 use Scalar::Util 'blessed';
 
-use Mouse::Attribute;
-use Mouse::Class;
+use Mouse::Meta::Attribute;
+use Mouse::Meta::Class;
 use Mouse::Object;
+use Mouse::TypeRegistry;
 
 do {
     my $CALLER;
 
     my %exports = (
         meta => sub {
-            my $meta = Mouse::Class->initialize($CALLER);
+            my $meta = Mouse::Meta::Class->initialize($CALLER);
             return sub { $meta };
         },
 
@@ -36,17 +37,17 @@ do {
                 $names = [$names] if !ref($names);
 
                 for my $name (@$names) {
-                    Mouse::Attribute->create($package, $name, @_);
+                    Mouse::Meta::Attribute->create($package, $name, @_);
                 }
             };
         },
 
         confess => sub {
-            return \&Carp::confess;
+            return \&confess;
         },
 
         blessed => sub {
-            return \&Scalar::Util::blessed;
+            return \&blessed;
         },
     );
 
@@ -61,8 +62,9 @@ do {
         strict->import;
         warnings->import;
 
-        no strict 'refs';
-        @{ $CALLER . '::ISA' } = 'Mouse::Object';
+        my $meta = Mouse::Meta::Class->initialize($CALLER);
+        $meta->superclasses('Mouse::Object')
+            unless $meta->superclasses;
 
         goto $exporter;
     }
@@ -81,23 +83,58 @@ do {
 sub load_class {
     my $class = shift;
 
+    if (ref($class) || !defined($class) || !length($class)) {
+        my $display = defined($class) ? $class : 'undef';
+        confess "Invalid class name ($display)";
+    }
+
+    return 1 if is_class_loaded($class);
+
     (my $file = "$class.pm") =~ s{::}{/}g;
 
     eval { CORE::require($file) };
-    confess "Could not load class ($class) because : $@"
-        if $@
-        && $@ !~ /^Can't locate .*? at /;
+    confess "Could not load class ($class) because : $@" if $@;
 
     return 1;
 }
 
+sub is_class_loaded {
+    my $class = shift;
+
+    return 0 if ref($class) || !defined($class) || !length($class);
+
+    # walk the symbol table tree to avoid autovififying
+    # \*{${main::}{"Foo::"}} == \*main::Foo::
+
+    my $pack = \*::;
+    foreach my $part (split('::', $class)) {
+        return 0 unless exists ${$$pack}{"${part}::"};
+        $pack = \*{${$$pack}{"${part}::"}};
+    }
+
+    # check for $VERSION or @ISA
+    return 1 if exists ${$$pack}{VERSION}
+             && defined *{${$$pack}{VERSION}}{SCALAR};
+    return 1 if exists ${$$pack}{ISA}
+             && defined *{${$$pack}{ISA}}{ARRAY};
+
+    # check for any method
+    foreach ( keys %{$$pack} ) {
+        next if substr($_, -2, 2) eq '::';
+        return 1 if defined *{${$$pack}{$_}}{CODE};
+    }
+
+    # fail
+    return 0;
+}
+
 1;
 
 __END__
 
 =head1 NAME
 
-Mouse - miniature Moose near the speed of light
+Mouse - Moose minus antlers
 
 =head1 VERSION
 
@@ -106,18 +143,28 @@ Version 0.01 released ???
 =head1 SYNOPSIS
 
     package Point;
+    use Mouse; # automatically turns on strict and warnings
+
+    has 'x' => (is => 'rw', isa => 'Int');
+    has 'y' => (is => 'rw', isa => 'Int');
+
+    sub clear {
+        my $self = shift;
+        $self->x(0);
+        $self->y(0);
+    }
+
+    package Point3D;
     use Mouse;
 
-    has x => (
-        is => 'rw',
-    );
+    extends 'Point';
 
-    has y => (
-        is        => 'rw',
-        default   => 0,
-        predicate => 'has_y',
-        clearer   => 'clear_y',
-    );
+    has 'z' => (is => 'rw', isa => 'Int');
+
+    #after 'clear' => sub {
+    #    my $self = shift;
+    #    $self->z(0);
+    #};
 
 =head1 DESCRIPTION
 
@@ -125,7 +172,7 @@ Moose.
 
 =head1 INTERFACE
 
-=head2 meta -> Mouse::Class
+=head2 meta -> Mouse::Meta::Class
 
 Returns this class' metaclass instance.
 
@@ -150,7 +197,7 @@ L<Scalar::Util/blessed> for your convenience.
 
 =head2 import
 
-Importing Mouse will set your class' superclass list to L<Mouse::Object>.
+Importing Mouse will default your class' superclass list to L<Mouse::Object>.
 You may use L</extends> to replace the superclass list.
 
 =head2 unimport
@@ -162,10 +209,16 @@ L</extends>) it will break loudly instead breaking subtly.
 
 =head2 load_class Class::Name
 
-This will load a given Class::Name> (or die if it's not loadable).
+This will load a given C<Class::Name> (or die if it's not loadable).
 This function can be used in place of tricks like
 C<eval "use $module"> or using C<require>.
 
+=head2 is_class_loaded Class::Name -> Bool
+
+Returns whether this class is actually loaded or not. It uses a heuristic which
+involves checking for the existence of C<$VERSION>, C<@ISA>, and any
+locally-defined method.
+
 =head1 AUTHOR
 
 Shawn M Moore, C<< <sartak at gmail.com> >>