die on attributes with no methods and no is => 'bare'
Hans Dieter Pearcey [Wed, 24 Jun 2009 18:15:40 +0000 (14:15 -0400)]
13 files changed:
Changes
lib/Moose/Meta/Attribute.pm
t/020_attributes/007_attribute_custom_metaclass.t
t/020_attributes/009_attribute_inherited_slot_specs.t
t/020_attributes/012_misc_attribute_tests.t
t/020_attributes/022_legal_options_for_inheritance.t
t/020_attributes/024_attribute_traits_parameterized.t
t/020_attributes/026_attribute_without_any_methods.t [new file with mode: 0644]
t/030_roles/017_extending_role_attrs.t
t/040_type_constraints/030_class_subtypes.t
t/050_metaclasses/014_goto_moose_import.t
t/500_test_moose/003_test_moose_has_attribute_ok.t
xt/author/pod_coverage.t

diff --git a/Changes b/Changes
index 1d1f1df..6a7d3cb 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,11 @@
 Also see Moose::Manual::Delta for more details of, and workarounds
 for, noteworthy changes.
 
+0.XX
+    * Moose::Meta::Attribute
+      - When adding an attribute to a metaclass, if the attribute has no
+        methods associated with, it will now throw an error. (hdp)
+
 0.83 Tue, Jun 23, 2009
     * Moose::Meta::Class
       - Fix _construct_instance not setting the special __MOP__ object
index 6d487aa..87e60ed 100644 (file)
@@ -290,6 +290,9 @@ sub _process_options {
                 $options->{accessor} ||= $name;
             }
         }
+        elsif ($options->{is} eq 'bare') {
+            # do nothing, but don't complain (later) about missing methods
+        }
         else {
             $class->throw_error("I do not understand this option (is => " . $options->{is} . ") on attribute ($name)", data => $options->{is});
         }
@@ -531,6 +534,25 @@ sub get_value {
 
 ## installing accessors
 
+sub attach_to_class {
+    my $self = shift;
+    unless (
+        $self->has_accessor
+        || $self->has_reader
+        || $self->has_writer
+        || $self->has_handles
+        # init_arg?
+        || @{ $self->associated_methods }
+        || ($self->_is_metadata || '') eq 'bare'
+    ) {
+        $self->throw_error(
+            'Attribute (' . $self->name . ') has no associated methods'
+            . ' (did you mean to provide an "is" argument?)'
+        )
+    }
+    return $self->SUPER::attach_to_class(@_);
+}
+
 sub accessor_metaclass { 'Moose::Meta::Method::Accessor' }
 
 sub install_accessors {
index de3cb5b..25c3d1b 100644 (file)
@@ -76,7 +76,7 @@ use Test::Exception;
     } '... the attribute metaclass alias worked correctly';
 
     ::lives_ok {
-        has 'bar' => (metaclass => 'Bar');
+        has 'bar' => (metaclass => 'Bar', is => 'bare');
     } '... the attribute metaclass alias worked correctly';
 }
 
index 46963b7..7903f9d 100644 (file)
@@ -42,8 +42,8 @@ use Test::Exception;
     has 'one_last_one' => (is => 'rw', isa => 'Ref');
 
     # this one will work here ....
-    has 'fail' => (isa => 'CodeRef');
-    has 'other_fail';
+    has 'fail' => (isa => 'CodeRef', is => 'bare');
+    has 'other_fail' => (is => 'bare');
 
     package Bar;
     use Moose;
index 8d02691..b788d7c 100644 (file)
@@ -17,7 +17,8 @@ use Test::Exception;
             documentation => q{
                 The 'foo' attribute is my favorite
                 attribute in the whole wide world.
-            }
+            },
+            is => 'bare',
         );
     }
 
@@ -256,8 +257,8 @@ use Test::Exception;
     use Moose;
 }
 
-lives_ok { OutOfClassTest::has('foo'); } 'create attr via direct sub call';
-lives_ok { OutOfClassTest->can('has')->('bar'); } 'create attr via can';
+lives_ok { OutOfClassTest::has('foo', is => 'bare'); } 'create attr via direct sub call';
+lives_ok { OutOfClassTest->can('has')->('bar', is => 'bare'); } 'create attr via can';
 
 ok(OutOfClassTest->meta->get_attribute('foo'), 'attr created from sub call');
 ok(OutOfClassTest->meta->get_attribute('bar'), 'attr created from can');
index e30cc97..c44b7d1 100644 (file)
@@ -26,7 +26,8 @@ use Test::More tests => 2;
 
     has 'bar' => (
       metaclass       => 'Bar::Meta::Attribute',
-      my_legal_option => sub { 'Bar' }
+      my_legal_option => sub { 'Bar' },
+      is => 'bare',
     );
 
     package Bar::B;
index c85f187..2561b34 100644 (file)
@@ -25,6 +25,7 @@ use Test::More tests => 4;
                 },
             },
         ],
+        is => 'bare',
     );
 }
 
@@ -40,6 +41,7 @@ use Test::More tests => 4;
                 },
             },
         ],
+        is => 'bare',
     );
 }
 
diff --git a/t/020_attributes/026_attribute_without_any_methods.t b/t/020_attributes/026_attribute_without_any_methods.t
new file mode 100644 (file)
index 0000000..c6f1348
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 2;
+
+use Moose ();
+use Moose::Meta::Class;
+
+my $meta = Moose::Meta::Class->create_anon_class;
+
+#local $TODO = 'not implemented yet';
+
+eval { $meta->add_attribute('foo') };
+like $@, qr/Attribute \(foo\) has no associated methods/,
+  'correct error message';
+
+ok(
+    eval { $meta->add_attribute('bar', is => 'bare'); 1 },
+    'add attribute with no methods',
+) or diag $@;
index df01d3d..e960a67 100644 (file)
@@ -151,6 +151,7 @@ is_deeply($quux->quux, ["hi"], "... still has the old ArrayRef value");
     for (1..3) {
         has "err$_" => (
             isa => 'Str | Int',
+            is => 'bare',
         );
     }
 
index 95ef25e..959b007 100644 (file)
@@ -94,6 +94,7 @@ like $isa_foo->get_message( Baz->new ), qr/^Validation failed for 'IsaFoo' faile
 
     has age => (
         isa => 'Positive',
+        is => 'bare',
     );
 }
 
@@ -127,6 +128,7 @@ class_type 'Negative' => message { "$_ is not a Negative Nancy" };
 
     has age => (
         isa => 'Negative',
+        is => 'bare',
     );
 }
 
index 41056a9..facf3e4 100644 (file)
@@ -31,7 +31,7 @@ use Test::Exception;
 
     MooseAlike1->import();
 
-    ::lives_ok( sub { has( 'size' ) },
+    ::lives_ok( sub { has( 'size', is => 'bare' ) },
                 'has was exported via MooseAlike1' );
 
     MooseAlike1->unimport();
@@ -68,7 +68,7 @@ isa_ok( Foo->meta(), 'Moose::Meta::Class' );
 
     MooseAlike2->import();
 
-    ::lives_ok( sub { has( 'size' ) },
+    ::lives_ok( sub { has( 'size', is => 'bare' ) },
                 'has was exported via MooseAlike2' );
 
     MooseAlike2->unimport();
index 957ad33..99e69f2 100644 (file)
@@ -14,7 +14,7 @@ BEGIN {
     package Foo;
     use Moose;
 
-    has 'foo';
+    has 'foo', is => 'bare';
 }
 
 {
@@ -23,7 +23,7 @@ BEGIN {
 
     extends 'Foo';
 
-    has 'bar';
+    has 'bar', is => 'bare';
 }
 
 
index 3464180..f5d36ff 100644 (file)
@@ -15,7 +15,12 @@ plan tests => scalar @modules;
 
 my %trustme = (
     'Moose'                  => ['make_immutable'],
-    'Moose::Meta::Attribute' => [ 'interpolate_class', 'throw_error' ],
+    'Moose::Meta::Attribute' => [
+        qw( interpolate_class
+            throw_error
+            attach_to_class
+            )
+    ],
     'Moose::Meta::Class'     => [
         qw( check_metaclass_compatibility
             construct_instance