Refactor many many things
[gitmo/Mouse.git] / lib / Mouse / Meta / Class.pm
index 1093e02..06c4f35 100644 (file)
@@ -78,38 +78,50 @@ sub get_all_method_names {
             $self->linearized_isa;
 }
 
-sub add_attribute {
+sub _process_attribute{
     my $self = shift;
+    my $name = shift;
 
-    if (@_ == 1 && blessed($_[0])) {
-        my $attr = shift @_;
-        $self->{'attributes'}{$attr->name} = $attr;
-    }
-    else {
-        my $names = shift @_;
-        $names = [$names] if !ref($names);
-        my $metaclass = 'Mouse::Meta::Attribute';
-        my %options   = (@_ == 1 ? %{$_[0]} : @_);
-
-        if ( my $metaclass_name = delete $options{metaclass} ) {
-            my $new_class = Mouse::Util::resolve_metaclass_alias(
-                'Attribute',
-                $metaclass_name
-            );
-            if ( $metaclass ne $new_class ) {
-                $metaclass = $new_class;
-            }
-        }
+    my $args = (@_ == 1) ? $_[0] : { @_ };
 
-        for my $name (@$names) {
-            if ($name =~ s/^\+//) {
-                $metaclass->clone_parent($self, $name, %options);
-            }
-            else {
-                $metaclass->create($self, $name, %options);
-            }
+    defined($name)
+        or $self->throw_error('You must provide a name for the attribute');
+
+    if ($name =~ s/^\+//) {
+        my $inherited_attr;
+
+        foreach my $class($self->linearized_isa){
+            my $meta = Mouse::Meta::Module::get_metaclass_by_name($class) or next;
+            $inherited_attr = $meta->get_attribute($name) and last;
         }
+
+        defined($inherited_attr)
+            or $self->throw_error("Could not find an attribute by the name of '$name' to inherit from in ".$self->name);
+
+        return $inherited_attr->clone_and_inherit_options($name, $args);
+    }
+    else{
+        return Mouse::Meta::Attribute->interpolate_class_and_new($name, $args);
+    }
+}
+
+sub add_attribute {
+    my $self = shift;
+
+    my $attr = blessed($_[0]) ? $_[0] : $self->_process_attribute(@_);
+
+    $attr->isa('Mouse::Meta::Attribute')
+        || $self->throw_error("Your attribute must be an instance of Mouse::Meta::Attribute (or a subclass)");
+
+    weaken( $attr->{associated_class} = $self );
+
+    $self->{attributes}{$attr->name} = $attr;
+    $attr->install_accessors();
+
+    if(!$attr->{associated_methods} && ($attr->{is} || '') ne 'bare'){
+        Carp::cluck(qq{Attribute (}.$attr->name.qq{) of class }.$self->name.qq{ has no associated methods (did you mean to provide an "is" argument?)});
     }
+    return $attr;
 }
 
 sub compute_all_applicable_attributes { shift->get_all_attributes(@_) }
@@ -138,24 +150,32 @@ sub new_object {
 
     my $instance = bless {}, $self->name;
 
+    $self->_initialize_instance($instance, \%args);
+    return $instance;
+}
+
+sub _initialize_instance{
+    my($self, $instance, $args) = @_;
+
     my @triggers_queue;
 
     foreach my $attribute ($self->get_all_attributes) {
         my $from = $attribute->init_arg;
         my $key  = $attribute->name;
 
-        if (defined($from) && exists($args{$from})) {
-            $args{$from} = $attribute->coerce_constraint($args{$from})
+        if (defined($from) && exists($args->{$from})) {
+            $args->{$from} = $attribute->coerce_constraint($args->{$from})
                 if $attribute->should_coerce;
-            $attribute->verify_against_type_constraint($args{$from});
 
-            $instance->{$key} = $args{$from};
+            $attribute->verify_against_type_constraint($args->{$from});
+
+            $instance->{$key} = $args->{$from};
 
             weaken($instance->{$key})
                 if ref($instance->{$key}) && $attribute->is_weak_ref;
 
             if ($attribute->has_trigger) {
-                push @triggers_queue, [ $attribute->trigger, $args{$from} ];
+                push @triggers_queue, [ $attribute->trigger, $args->{$from} ];
             }
         }
         else {