X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FClass%2FMOP.pm;h=524140faa7c58b33927bddc268b2ee21e66a07fa;hb=3e2c8600b98f2c7c0c84d1a94a565c801ca7aa3d;hp=e3c38ffb7becd14d2c299fabf38c4c9b24e93560;hpb=efc98200d49cae9fb74285a58d12e3b988da0a97;p=gitmo%2FClass-MOP.git diff --git a/lib/Class/MOP.pm b/lib/Class/MOP.pm index e3c38ff..524140f 100644 --- a/lib/Class/MOP.pm +++ b/lib/Class/MOP.pm @@ -10,7 +10,11 @@ use MRO::Compat; use Carp 'confess'; use Scalar::Util 'weaken', 'reftype', 'blessed'; +use Try::Tiny; +use Class::MOP::Mixin::AttributeCore; +use Class::MOP::Mixin::HasAttributes; +use Class::MOP::Mixin::HasMethods; use Class::MOP::Class; use Class::MOP::Attribute; use Class::MOP::Method; @@ -20,16 +24,11 @@ BEGIN { ? sub () { 0 } : sub () { 1 }; - sub HAVE_ISAREV () { - Carp::cluck("Class::MOP::HAVE_ISAREV is deprecated and will be removed in a future release. It has always returned 1 anyway."); - return 1; - } - # this is either part of core or set up appropriately by MRO::Compat *check_package_cache_flag = \&mro::get_pkg_gen; } -our $VERSION = '0.89'; +our $VERSION = '0.97_01'; our $XS_VERSION = $VERSION; $VERSION = eval $VERSION; our $AUTHORITY = 'cpan:STEVAN'; @@ -80,7 +79,7 @@ sub _class_to_pmfile { sub load_first_existing_class { my @classes = @_ - or return; + or return; foreach my $class (@classes) { unless ( _is_valid_class_name($class) ) { @@ -91,54 +90,40 @@ sub load_first_existing_class { my $found; my %exceptions; - for my $class (@classes) { - my $pmfile = _class_to_pmfile($class); - my $e = _try_load_one_class($class); - if ($e) { - $exceptions{$class} = $e; - last if $e !~ /^Can't locate \Q$pmfile\E in \@INC/; - } - else { - $found = $class; - last; - } - } + for my $class (@classes) { + my $file = _class_to_pmfile($class); - return $found if $found; + return $class if is_class_loaded($class);; - confess join( - "\n", - map { - sprintf( - "Could not load class (%s) because : %s", $_, - $exceptions{$_} - ) + return $class if try { + local $SIG{__DIE__}; + require $file; + return 1; + } + catch { + unless (/^Can't locate \Q$file\E in \@INC/) { + confess "Couldn't load class ($class) because: $_"; } - grep { - exists $exceptions{$_} - } @classes - ); -} - -sub _try_load_one_class { - my $class = shift; - - return if is_class_loaded($class); - my $file = _class_to_pmfile($class); + return; + }; + } - return do { - local $@; - local $SIG{__DIE__}; - eval { require($file) }; - $@; - }; + if ( @classes > 1 ) { + confess "Can't locate any of @classes in \@INC (\@INC contains: @INC)."; + } else { + confess "Can't locate " . _class_to_pmfile($classes[0]) . " in \@INC (\@INC contains: @INC)."; + } } sub load_class { - my $class = load_first_existing_class($_[0]); - return get_metaclass_by_name($class) || $class; + load_first_existing_class($_[0]); + + # 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_valid_class_name { @@ -153,18 +138,6 @@ sub _is_valid_class_name { return 0; } -sub subname { - require Sub::Name; - Carp::carp("Class::MOP::subname is deprecated. Please use Sub::Name directly."); - goto \&Sub::Name::subname; -} - -sub in_global_destruction { - require Devel::GlobalDestruction; - Carp::carp("Class::MOP::in_global_destruction is deprecated. Please use Devel::GlobalDestruction directly."); - goto \&Devel::GlobalDestruction::in_global_destruction; -} - ## ---------------------------------------------------------------------------- ## Setting up our environment ... ## ---------------------------------------------------------------------------- @@ -190,6 +163,75 @@ sub in_global_destruction { # inherit them using _construct_instance ## -------------------------------------------------------- +## Class::MOP::Mixin::HasMethods + +Class::MOP::Mixin::HasMethods->meta->add_attribute( + Class::MOP::Attribute->new('_methods' => ( + reader => { + # NOTE: + # we just alias the original method + # rather than re-produce it here + '_full_method_map' => \&Class::MOP::Mixin::HasMethods::_full_method_map + }, + default => sub { {} } + )) +); + +Class::MOP::Mixin::HasMethods->meta->add_attribute( + Class::MOP::Attribute->new('method_metaclass' => ( + reader => { + # NOTE: + # we just alias the original method + # rather than re-produce it here + 'method_metaclass' => \&Class::MOP::Mixin::HasMethods::method_metaclass + }, + default => 'Class::MOP::Method', + )) +); + +Class::MOP::Mixin::HasMethods->meta->add_attribute( + Class::MOP::Attribute->new('wrapped_method_metaclass' => ( + reader => { + # NOTE: + # we just alias the original method + # rather than re-produce it here + 'wrapped_method_metaclass' => \&Class::MOP::Mixin::HasMethods::wrapped_method_metaclass + }, + default => 'Class::MOP::Method::Wrapped', + )) +); + +## -------------------------------------------------------- +## Class::MOP::Mixin::HasMethods + +Class::MOP::Mixin::HasAttributes->meta->add_attribute( + Class::MOP::Attribute->new('attributes' => ( + reader => { + # NOTE: we need to do this in order + # for the instance meta-object to + # not fall into meta-circular death + # + # we just alias the original method + # rather than re-produce it here + '_attribute_map' => \&Class::MOP::Mixin::HasAttributes::_attribute_map + }, + default => sub { {} } + )) +); + +Class::MOP::Mixin::HasAttributes->meta->add_attribute( + Class::MOP::Attribute->new('attribute_metaclass' => ( + reader => { + # NOTE: + # we just alias the original method + # rather than re-produce it here + 'attribute_metaclass' => \&Class::MOP::Mixin::HasAttributes::attribute_metaclass + }, + default => 'Class::MOP::Attribute', + )) +); + +## -------------------------------------------------------- ## Class::MOP::Package Class::MOP::Package->meta->add_attribute( @@ -268,33 +310,6 @@ Class::MOP::Module->meta->add_attribute( ## Class::MOP::Class Class::MOP::Class->meta->add_attribute( - Class::MOP::Attribute->new('attributes' => ( - reader => { - # NOTE: we need to do this in order - # for the instance meta-object to - # not fall into meta-circular death - # - # we just alias the original method - # rather than re-produce it here - 'get_attribute_map' => \&Class::MOP::Class::get_attribute_map - }, - default => sub { {} } - )) -); - -Class::MOP::Class->meta->add_attribute( - Class::MOP::Attribute->new('methods' => ( - reader => { - # NOTE: - # we just alias the original method - # rather than re-produce it here - 'get_method_map' => \&Class::MOP::Class::get_method_map - }, - default => sub { {} } - )) -); - -Class::MOP::Class->meta->add_attribute( Class::MOP::Attribute->new('superclasses' => ( accessor => { # NOTE: @@ -308,42 +323,6 @@ Class::MOP::Class->meta->add_attribute( ); Class::MOP::Class->meta->add_attribute( - Class::MOP::Attribute->new('attribute_metaclass' => ( - reader => { - # NOTE: - # we just alias the original method - # rather than re-produce it here - 'attribute_metaclass' => \&Class::MOP::Class::attribute_metaclass - }, - default => 'Class::MOP::Attribute', - )) -); - -Class::MOP::Class->meta->add_attribute( - Class::MOP::Attribute->new('method_metaclass' => ( - reader => { - # NOTE: - # we just alias the original method - # rather than re-produce it here - 'method_metaclass' => \&Class::MOP::Class::method_metaclass - }, - default => 'Class::MOP::Method', - )) -); - -Class::MOP::Class->meta->add_attribute( - Class::MOP::Attribute->new('wrapped_method_metaclass' => ( - reader => { - # NOTE: - # we just alias the original method - # rather than re-produce it here - 'wrapped_method_metaclass' => \&Class::MOP::Class::wrapped_method_metaclass - }, - default => 'Class::MOP::Method::Wrapped', - )) -); - -Class::MOP::Class->meta->add_attribute( Class::MOP::Attribute->new('instance_metaclass' => ( reader => { # NOTE: we need to do this in order @@ -401,9 +380,8 @@ Class::MOP::Class->meta->add_attribute( # _construct_class_instance method. ## -------------------------------------------------------- -## Class::MOP::Attribute - -Class::MOP::Attribute->meta->add_attribute( +## Class::MOP::Mixin::AttributeCore +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('name' => ( reader => { # NOTE: we need to do this in order @@ -412,106 +390,108 @@ Class::MOP::Attribute->meta->add_attribute( # # we just alias the original method # rather than re-produce it here - 'name' => \&Class::MOP::Attribute::name - } - )) -); - -Class::MOP::Attribute->meta->add_attribute( - Class::MOP::Attribute->new('associated_class' => ( - reader => { - # NOTE: we need to do this in order - # for the instance meta-object to - # not fall into meta-circular death - # - # we just alias the original method - # rather than re-produce it here - 'associated_class' => \&Class::MOP::Attribute::associated_class + 'name' => \&Class::MOP::Mixin::AttributeCore::name } )) ); -Class::MOP::Attribute->meta->add_attribute( +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('accessor' => ( - reader => { 'accessor' => \&Class::MOP::Attribute::accessor }, - predicate => { 'has_accessor' => \&Class::MOP::Attribute::has_accessor }, + reader => { 'accessor' => \&Class::MOP::Mixin::AttributeCore::accessor }, + predicate => { 'has_accessor' => \&Class::MOP::Mixin::AttributeCore::has_accessor }, )) ); -Class::MOP::Attribute->meta->add_attribute( +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('reader' => ( - reader => { 'reader' => \&Class::MOP::Attribute::reader }, - predicate => { 'has_reader' => \&Class::MOP::Attribute::has_reader }, + reader => { 'reader' => \&Class::MOP::Mixin::AttributeCore::reader }, + predicate => { 'has_reader' => \&Class::MOP::Mixin::AttributeCore::has_reader }, )) ); -Class::MOP::Attribute->meta->add_attribute( +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('initializer' => ( - reader => { 'initializer' => \&Class::MOP::Attribute::initializer }, - predicate => { 'has_initializer' => \&Class::MOP::Attribute::has_initializer }, + reader => { 'initializer' => \&Class::MOP::Mixin::AttributeCore::initializer }, + predicate => { 'has_initializer' => \&Class::MOP::Mixin::AttributeCore::has_initializer }, )) ); -Class::MOP::Attribute->meta->add_attribute( +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('definition_context' => ( - reader => { 'definition_context' => \&Class::MOP::Attribute::definition_context }, + reader => { 'definition_context' => \&Class::MOP::Mixin::AttributeCore::definition_context }, )) ); -Class::MOP::Attribute->meta->add_attribute( +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('writer' => ( - reader => { 'writer' => \&Class::MOP::Attribute::writer }, - predicate => { 'has_writer' => \&Class::MOP::Attribute::has_writer }, + reader => { 'writer' => \&Class::MOP::Mixin::AttributeCore::writer }, + predicate => { 'has_writer' => \&Class::MOP::Mixin::AttributeCore::has_writer }, )) ); -Class::MOP::Attribute->meta->add_attribute( +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('predicate' => ( - reader => { 'predicate' => \&Class::MOP::Attribute::predicate }, - predicate => { 'has_predicate' => \&Class::MOP::Attribute::has_predicate }, + reader => { 'predicate' => \&Class::MOP::Mixin::AttributeCore::predicate }, + predicate => { 'has_predicate' => \&Class::MOP::Mixin::AttributeCore::has_predicate }, )) ); -Class::MOP::Attribute->meta->add_attribute( +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('clearer' => ( - reader => { 'clearer' => \&Class::MOP::Attribute::clearer }, - predicate => { 'has_clearer' => \&Class::MOP::Attribute::has_clearer }, + reader => { 'clearer' => \&Class::MOP::Mixin::AttributeCore::clearer }, + predicate => { 'has_clearer' => \&Class::MOP::Mixin::AttributeCore::has_clearer }, )) ); -Class::MOP::Attribute->meta->add_attribute( +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('builder' => ( - reader => { 'builder' => \&Class::MOP::Attribute::builder }, - predicate => { 'has_builder' => \&Class::MOP::Attribute::has_builder }, + reader => { 'builder' => \&Class::MOP::Mixin::AttributeCore::builder }, + predicate => { 'has_builder' => \&Class::MOP::Mixin::AttributeCore::has_builder }, )) ); -Class::MOP::Attribute->meta->add_attribute( +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('init_arg' => ( - reader => { 'init_arg' => \&Class::MOP::Attribute::init_arg }, - predicate => { 'has_init_arg' => \&Class::MOP::Attribute::has_init_arg }, + reader => { 'init_arg' => \&Class::MOP::Mixin::AttributeCore::init_arg }, + predicate => { 'has_init_arg' => \&Class::MOP::Mixin::AttributeCore::has_init_arg }, )) ); -Class::MOP::Attribute->meta->add_attribute( +Class::MOP::Mixin::AttributeCore->meta->add_attribute( Class::MOP::Attribute->new('default' => ( # default has a custom 'reader' method ... - predicate => { 'has_default' => \&Class::MOP::Attribute::has_default }, + predicate => { 'has_default' => \&Class::MOP::Mixin::AttributeCore::has_default }, + )) +); + +Class::MOP::Mixin::AttributeCore->meta->add_attribute( + Class::MOP::Attribute->new('insertion_order' => ( + 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 }, )) ); +## -------------------------------------------------------- +## Class::MOP::Attribute Class::MOP::Attribute->meta->add_attribute( - Class::MOP::Attribute->new('associated_methods' => ( - reader => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods }, - default => sub { [] } + Class::MOP::Attribute->new('associated_class' => ( + reader => { + # NOTE: we need to do this in order + # for the instance meta-object to + # not fall into meta-circular death + # + # we just alias the original method + # rather than re-produce it here + 'associated_class' => \&Class::MOP::Attribute::associated_class + } )) ); Class::MOP::Attribute->meta->add_attribute( - Class::MOP::Attribute->new('insertion_order' => ( - reader => { 'insertion_order' => \&Class::MOP::Attribute::insertion_order }, - writer => { '_set_insertion_order' => \&Class::MOP::Attribute::_set_insertion_order }, - predicate => { 'has_insertion_order' => \&Class::MOP::Attribute::has_insertion_order }, + Class::MOP::Attribute->new('associated_methods' => ( + reader => { 'associated_methods' => \&Class::MOP::Attribute::associated_methods }, + default => sub { [] } )) ); @@ -676,6 +656,7 @@ Class::MOP::Instance->meta->add_attribute( ), ); +require Class::MOP::Deprecated unless our $no_deprecated; # we need the meta instance of the meta instance to be created now, in order # for the constructor to be able to use it @@ -691,8 +672,7 @@ undef Class::MOP::Instance->meta->{_package_cache_flag}; # the compile time of the MOP, and gives us no actual benefits. $_->meta->make_immutable( - inline_constructor => 1, - replace_constructor => 1, + inline_constructor => 0, constructor_name => "_new", inline_accessors => 0, ) for qw/ @@ -714,6 +694,17 @@ $_->meta->make_immutable( Class::MOP::Method::Wrapped /; +$_->meta->make_immutable( + inline_constructor => 0, + constructor_name => undef, + inline_accessors => 0, +) for qw/ + Class::MOP::Mixin + Class::MOP::Mixin::AttributeCore + Class::MOP::Mixin::HasAttributes + Class::MOP::Mixin::HasMethods +/; + 1; __END__ @@ -928,8 +919,11 @@ Note that these are all called as B. This will load the specified C<$class_name>, if it is not already loaded (as reported by C). This function can be used in place of tricks like C or using C -unconditionally. This will return the metaclass of C<$class_name> if -one exists, otherwise it will return C<$class_name>. +unconditionally. + +If the module cannot be loaded, an exception is thrown. + +For historical reasons, this function explicitly returns a true value. =item B @@ -1082,7 +1076,7 @@ L =over 4 -=item L +=item L =item L @@ -1157,7 +1151,7 @@ Dylan Hardison =head1 COPYRIGHT AND LICENSE -Copyright 2006-2009 by Infinity Interactive, Inc. +Copyright 2006-2010 by Infinity Interactive, Inc. L