document that some functions moved to Class::Load
[gitmo/Moose.git] / lib / Class / MOP.pm
index f079096..338291b 100644 (file)
@@ -9,6 +9,7 @@ use 5.008;
 use MRO::Compat;
 
 use Carp          'confess';
+use Class::Load   ();
 use Scalar::Util  'weaken', 'isweak', 'reftype', 'blessed';
 use Data::OptList;
 use Try::Tiny;
@@ -66,89 +67,25 @@ XSLoader::load(
     # because I don't yet see a good reason to do so.
 }
 
-sub _class_to_pmfile {
-    my $class = shift;
-
-    my $file = $class . '.pm';
-    $file =~ s{::}{/}g;
-
-    return $file;
+sub load_class {
+    goto &Class::Load::load_class;
 }
 
 sub load_first_existing_class {
-    my $classes = Data::OptList::mkopt(\@_)
-      or return;
-
-    foreach my $class (@{ $classes }) {
-        my $name = $class->[0];
-        unless ( _is_valid_class_name($name) ) {
-            my $display = defined($name) ? $name : 'undef';
-            confess "Invalid class name ($display)";
-        }
-    }
-
-    my $found;
-    my %exceptions;
-
-    for my $class (@{ $classes }) {
-        my ($name, $options) = @{ $class };
-
-        if ($options) {
-            return $name if is_class_loaded($name, $options);
-            if (is_class_loaded($name)) {
-                # we already know it's loaded and too old, but we call
-                # ->VERSION anyway to generate the exception for us
-                $name->VERSION($options->{-version});
-            }
-        }
-        else {
-            return $name if is_class_loaded($name);
-        }
-
-        my $file = _class_to_pmfile($name);
-        return $name if try {
-            local $SIG{__DIE__};
-            require $file;
-            $name->VERSION($options->{-version})
-                if defined $options->{-version};
-            return 1;
-        }
-        catch {
-            unless (/^Can't locate \Q$file\E in \@INC/) {
-                confess "Couldn't load class ($name) because: $_";
-            }
-
-            return;
-        };
-    }
-
-    if ( @{ $classes } > 1 ) {
-        my @list = map { $_->[0] } @{ $classes };
-        confess "Can't locate any of @list in \@INC (\@INC contains: @INC).";
-    } else {
-        confess "Can't locate " . _class_to_pmfile($classes->[0]->[0]) . " in \@INC (\@INC contains: @INC).";
-    }
+    goto &Class::Load::load_first_existing_class;
 }
 
-sub load_class {
-    load_first_existing_class($_[0], ref $_[1] ? $_[1] : ());
-
-    # This is done to avoid breaking code which checked the return value. Said
-    # code is dumb. The return value was _always_ true, since it dies on
-    # failure!
-    return 1;
+sub is_class_loaded {
+    goto &Class::Load::is_class_loaded;
 }
 
-sub _is_valid_class_name {
-    my $class = shift;
+sub _definition_context {
+    my %context;
+    @context{qw(package file line)} = caller(1);
 
-    return 0 if ref($class);
-    return 0 unless defined($class);
-    return 0 unless length($class);
-
-    return 1 if $class =~ /^\w+(?:::\w+)*$/;
-
-    return 0;
+    return (
+        definition_context => \%context,
+    );
 }
 
 ## ----------------------------------------------------------------------------
@@ -186,7 +123,8 @@ Class::MOP::Mixin::HasMethods->meta->add_attribute(
             # rather than re-produce it here
             '_method_map' => \&Class::MOP::Mixin::HasMethods::_method_map
         },
-        default => sub { {} }
+        default => sub { {} },
+        _definition_context(),
     ))
 );
 
@@ -199,6 +137,7 @@ Class::MOP::Mixin::HasMethods->meta->add_attribute(
             'method_metaclass' => \&Class::MOP::Mixin::HasMethods::method_metaclass
         },
         default  => 'Class::MOP::Method',
+        _definition_context(),
     ))
 );
 
@@ -211,6 +150,7 @@ Class::MOP::Mixin::HasMethods->meta->add_attribute(
             'wrapped_method_metaclass' => \&Class::MOP::Mixin::HasMethods::wrapped_method_metaclass
         },
         default  => 'Class::MOP::Method::Wrapped',
+        _definition_context(),
     ))
 );
 
@@ -228,7 +168,8 @@ Class::MOP::Mixin::HasAttributes->meta->add_attribute(
             # rather than re-produce it here
             '_attribute_map' => \&Class::MOP::Mixin::HasAttributes::_attribute_map
         },
-        default  => sub { {} }
+        default  => sub { {} },
+        _definition_context(),
     ))
 );
 
@@ -241,6 +182,7 @@ Class::MOP::Mixin::HasAttributes->meta->add_attribute(
             'attribute_metaclass' => \&Class::MOP::Mixin::HasAttributes::attribute_metaclass
         },
         default  => 'Class::MOP::Attribute',
+        _definition_context(),
     ))
 );
 
@@ -258,6 +200,7 @@ Class::MOP::Package->meta->add_attribute(
             # rather than re-produce it here
             'name' => \&Class::MOP::Package::name
         },
+        _definition_context(),
     ))
 );
 
@@ -270,7 +213,8 @@ Class::MOP::Package->meta->add_attribute(
             'namespace' => \&Class::MOP::Package::namespace
         },
         init_arg => undef,
-        default  => sub { \undef }
+        default  => sub { \undef },
+        _definition_context(),
     ))
 );
 
@@ -296,7 +240,8 @@ Class::MOP::Module->meta->add_attribute(
             'version' => \&Class::MOP::Module::version
         },
         init_arg => undef,
-        default  => sub { \undef }
+        default  => sub { \undef },
+        _definition_context(),
     ))
 );
 
@@ -315,7 +260,8 @@ Class::MOP::Module->meta->add_attribute(
             'authority' => \&Class::MOP::Module::authority
         },
         init_arg => undef,
-        default  => sub { \undef }
+        default  => sub { \undef },
+        _definition_context(),
     ))
 );
 
@@ -331,7 +277,8 @@ Class::MOP::Class->meta->add_attribute(
             'superclasses' => \&Class::MOP::Class::superclasses
         },
         init_arg => undef,
-        default  => sub { \undef }
+        default  => sub { \undef },
+        _definition_context(),
     ))
 );
 
@@ -347,6 +294,7 @@ Class::MOP::Class->meta->add_attribute(
             'instance_metaclass' => \&Class::MOP::Class::instance_metaclass
         },
         default  => 'Class::MOP::Instance',
+        _definition_context(),
     ))
 );
 
@@ -356,6 +304,7 @@ Class::MOP::Class->meta->add_attribute(
             'immutable_trait' => \&Class::MOP::Class::immutable_trait
         },
         default => "Class::MOP::Class::Immutable::Trait",
+        _definition_context(),
     ))
 );
 
@@ -365,6 +314,7 @@ Class::MOP::Class->meta->add_attribute(
             'constructor_name' => \&Class::MOP::Class::constructor_name,
         },
         default => "new",
+        _definition_context(),
     ))
 );
 
@@ -374,6 +324,7 @@ Class::MOP::Class->meta->add_attribute(
             'constructor_class' => \&Class::MOP::Class::constructor_class,
         },
         default => "Class::MOP::Method::Constructor",
+        _definition_context(),
     ))
 );
 
@@ -383,6 +334,7 @@ Class::MOP::Class->meta->add_attribute(
         reader   => {
             'destructor_class' => \&Class::MOP::Class::destructor_class,
         },
+        _definition_context(),
     ))
 );
 
@@ -404,7 +356,8 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
             # we just alias the original method
             # rather than re-produce it here
             'name' => \&Class::MOP::Mixin::AttributeCore::name
-        }
+        },
+        _definition_context(),
     ))
 );
 
@@ -412,6 +365,7 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
     Class::MOP::Attribute->new('accessor' => (
         reader    => { 'accessor'     => \&Class::MOP::Mixin::AttributeCore::accessor     },
         predicate => { 'has_accessor' => \&Class::MOP::Mixin::AttributeCore::has_accessor },
+        _definition_context(),
     ))
 );
 
@@ -419,6 +373,7 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
     Class::MOP::Attribute->new('reader' => (
         reader    => { 'reader'     => \&Class::MOP::Mixin::AttributeCore::reader     },
         predicate => { 'has_reader' => \&Class::MOP::Mixin::AttributeCore::has_reader },
+        _definition_context(),
     ))
 );
 
@@ -426,12 +381,14 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
     Class::MOP::Attribute->new('initializer' => (
         reader    => { 'initializer'     => \&Class::MOP::Mixin::AttributeCore::initializer     },
         predicate => { 'has_initializer' => \&Class::MOP::Mixin::AttributeCore::has_initializer },
+        _definition_context(),
     ))
 );
 
 Class::MOP::Mixin::AttributeCore->meta->add_attribute(
     Class::MOP::Attribute->new('definition_context' => (
         reader    => { 'definition_context'     => \&Class::MOP::Mixin::AttributeCore::definition_context     },
+        _definition_context(),
     ))
 );
 
@@ -439,6 +396,7 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
     Class::MOP::Attribute->new('writer' => (
         reader    => { 'writer'     => \&Class::MOP::Mixin::AttributeCore::writer     },
         predicate => { 'has_writer' => \&Class::MOP::Mixin::AttributeCore::has_writer },
+        _definition_context(),
     ))
 );
 
@@ -446,6 +404,7 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
     Class::MOP::Attribute->new('predicate' => (
         reader    => { 'predicate'     => \&Class::MOP::Mixin::AttributeCore::predicate     },
         predicate => { 'has_predicate' => \&Class::MOP::Mixin::AttributeCore::has_predicate },
+        _definition_context(),
     ))
 );
 
@@ -453,6 +412,7 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
     Class::MOP::Attribute->new('clearer' => (
         reader    => { 'clearer'     => \&Class::MOP::Mixin::AttributeCore::clearer     },
         predicate => { 'has_clearer' => \&Class::MOP::Mixin::AttributeCore::has_clearer },
+        _definition_context(),
     ))
 );
 
@@ -460,6 +420,7 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
     Class::MOP::Attribute->new('builder' => (
         reader    => { 'builder'     => \&Class::MOP::Mixin::AttributeCore::builder     },
         predicate => { 'has_builder' => \&Class::MOP::Mixin::AttributeCore::has_builder },
+        _definition_context(),
     ))
 );
 
@@ -467,6 +428,7 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
     Class::MOP::Attribute->new('init_arg' => (
         reader    => { 'init_arg'     => \&Class::MOP::Mixin::AttributeCore::init_arg     },
         predicate => { 'has_init_arg' => \&Class::MOP::Mixin::AttributeCore::has_init_arg },
+        _definition_context(),
     ))
 );
 
@@ -474,6 +436,7 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
     Class::MOP::Attribute->new('default' => (
         # default has a custom 'reader' method ...
         predicate => { 'has_default' => \&Class::MOP::Mixin::AttributeCore::has_default },
+        _definition_context(),
     ))
 );
 
@@ -482,6 +445,7 @@ Class::MOP::Mixin::AttributeCore->meta->add_attribute(
         reader      => { 'insertion_order' => \&Class::MOP::Mixin::AttributeCore::insertion_order },
         writer      => { '_set_insertion_order' => \&Class::MOP::Mixin::AttributeCore::_set_insertion_order },
         predicate   => { 'has_insertion_order' => \&Class::MOP::Mixin::AttributeCore::has_insertion_order },
+        _definition_context(),
     ))
 );
 
@@ -497,14 +461,16 @@ Class::MOP::Attribute->meta->add_attribute(
             # we just alias the original method
             # rather than re-produce it here
             'associated_class' => \&Class::MOP::Attribute::associated_class
-        }
+        },
+        _definition_context(),
     ))
 );
 
 Class::MOP::Attribute->meta->add_attribute(
     Class::MOP::Attribute->new('associated_methods' => (
         reader   => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods },
-        default  => sub { [] }
+        default  => sub { [] },
+        _definition_context(),
     ))
 );
 
@@ -518,24 +484,28 @@ Class::MOP::Attribute->meta->add_method('clone' => sub {
 Class::MOP::Method->meta->add_attribute(
     Class::MOP::Attribute->new('body' => (
         reader   => { 'body' => \&Class::MOP::Method::body },
+        _definition_context(),
     ))
 );
 
 Class::MOP::Method->meta->add_attribute(
     Class::MOP::Attribute->new('associated_metaclass' => (
         reader   => { 'associated_metaclass' => \&Class::MOP::Method::associated_metaclass },
+        _definition_context(),
     ))
 );
 
 Class::MOP::Method->meta->add_attribute(
     Class::MOP::Attribute->new('package_name' => (
         reader   => { 'package_name' => \&Class::MOP::Method::package_name },
+        _definition_context(),
     ))
 );
 
 Class::MOP::Method->meta->add_attribute(
     Class::MOP::Attribute->new('name' => (
         reader   => { 'name' => \&Class::MOP::Method::name },
+        _definition_context(),
     ))
 );
 
@@ -543,6 +513,7 @@ Class::MOP::Method->meta->add_attribute(
     Class::MOP::Attribute->new('original_method' => (
         reader   => { 'original_method'      => \&Class::MOP::Method::original_method },
         writer   => { '_set_original_method' => \&Class::MOP::Method::_set_original_method },
+        _definition_context(),
     ))
 );
 
@@ -555,7 +526,9 @@ Class::MOP::Method->meta->add_attribute(
 # practices of attributes, but we put
 # it here for completeness
 Class::MOP::Method::Wrapped->meta->add_attribute(
-    Class::MOP::Attribute->new('modifier_table')
+    Class::MOP::Attribute->new('modifier_table' => (
+        _definition_context(),
+    ))
 );
 
 ## --------------------------------------------------------
@@ -564,13 +537,15 @@ Class::MOP::Method::Wrapped->meta->add_attribute(
 Class::MOP::Method::Generated->meta->add_attribute(
     Class::MOP::Attribute->new('is_inline' => (
         reader   => { 'is_inline' => \&Class::MOP::Method::Generated::is_inline },
-        default  => 0, 
+        default  => 0,
+        _definition_context(),
     ))
 );
 
 Class::MOP::Method::Generated->meta->add_attribute(
     Class::MOP::Attribute->new('definition_context' => (
         reader   => { 'definition_context' => \&Class::MOP::Method::Generated::definition_context },
+        _definition_context(),
     ))
 );
 
@@ -581,6 +556,7 @@ Class::MOP::Method::Generated->meta->add_attribute(
 Class::MOP::Method::Inlined->meta->add_attribute(
     Class::MOP::Attribute->new('_expected_method_class' => (
         reader   => { '_expected_method_class' => \&Class::MOP::Method::Inlined::_expected_method_class },
+        _definition_context(),
     ))
 );
 
@@ -592,12 +568,14 @@ Class::MOP::Method::Accessor->meta->add_attribute(
         reader   => {
             'associated_attribute' => \&Class::MOP::Method::Accessor::associated_attribute
         },
+        _definition_context(),
     ))
 );
 
 Class::MOP::Method::Accessor->meta->add_attribute(
     Class::MOP::Attribute->new('accessor_type' => (
         reader   => { 'accessor_type' => \&Class::MOP::Method::Accessor::accessor_type },
+        _definition_context(),
     ))
 );
 
@@ -609,7 +587,8 @@ Class::MOP::Method::Constructor->meta->add_attribute(
         reader   => {
             'options' => \&Class::MOP::Method::Constructor::options
         },
-        default  => sub { +{} }
+        default  => sub { +{} },
+        _definition_context(),
     ))
 );
 
@@ -619,6 +598,7 @@ Class::MOP::Method::Constructor->meta->add_attribute(
         reader   => {
             'associated_metaclass' => \&Class::MOP::Method::Constructor::associated_metaclass
         },
+        _definition_context(),
     ))
 );
 
@@ -632,6 +612,7 @@ Class::MOP::Method::Constructor->meta->add_attribute(
 Class::MOP::Instance->meta->add_attribute(
     Class::MOP::Attribute->new('associated_metaclass',
         reader   => { associated_metaclass => \&Class::MOP::Instance::associated_metaclass },
+        _definition_context(),
     ),
 );
 
@@ -641,24 +622,28 @@ Class::MOP::Instance->meta->add_attribute(
         reader   => { _class_name => \&Class::MOP::Instance::_class_name },
         #lazy     => 1, # not yet supported by Class::MOP but out our version does it anyway
         #default  => sub { $_[0]->associated_metaclass->name },
+        _definition_context(),
     ),
 );
 
 Class::MOP::Instance->meta->add_attribute(
     Class::MOP::Attribute->new('attributes',
         reader   => { attributes => \&Class::MOP::Instance::get_all_attributes },
+        _definition_context(),
     ),
 );
 
 Class::MOP::Instance->meta->add_attribute(
     Class::MOP::Attribute->new('slots',
         reader   => { slots => \&Class::MOP::Instance::slots },
+        _definition_context(),
     ),
 );
 
 Class::MOP::Instance->meta->add_attribute(
     Class::MOP::Attribute->new('slot_hash',
         reader   => { slot_hash => \&Class::MOP::Instance::slot_hash },
+        _definition_context(),
     ),
 );
 
@@ -932,37 +917,6 @@ Note that these are all called as B<functions, not methods>.
 
 =over 4
 
-=item B<Class::MOP::load_class($class_name, \%options?)>
-
-This will load the specified C<$class_name>, if it is not already
-loaded (as reported by C<is_class_loaded>). This function can be used
-in place of tricks like C<eval "use $module"> or using C<require>
-unconditionally.
-
-If the module cannot be loaded, an exception is thrown.
-
-You can pass a hash reference with options as second argument. The
-only option currently recognized is C<-version>, which will ensure
-that the loaded class has at least the required version.
-
-For historical reasons, this function explicitly returns a true value.
-
-=item B<Class::MOP::is_class_loaded($class_name, \%options?)>
-
-Returns a boolean indicating whether or not C<$class_name> has been
-loaded.
-
-This does a basic check of the symbol table to try and determine as
-best it can if the C<$class_name> is loaded, it is probably correct
-about 99% of the time, but it can be fooled into reporting false
-positives. In particular, loading any of the core L<IO> modules will
-cause most of the rest of the core L<IO> modules to falsely report
-having been loaded, due to the way the base L<IO> module works.
-
-You can pass a hash reference with options as second argument. The
-only option currently recognized is C<-version>, which will ensure
-that the loaded class has at least the required version.
-
 =item B<Class::MOP::get_code_info($code)>
 
 This function returns two values, the name of the package the C<$code>
@@ -1034,6 +988,11 @@ This will remove the metaclass stored in the C<$name> key.
 
 =back
 
+Some utility functions (such as C<Class::MOP::load_class>) that 
+were previously defined in C<Class::MOP> regarding loading of 
+classes have been extracted to L<Class::Load>. Please see there 
+for documentation.
+
 =head1 SEE ALSO
 
 =head2 Books