Revision history for Mouse
0.50_03
+ * Mouse::Meta::Attribute
+ - Catch up about Moose 0.84 about warnings (gfx)
+ - If an attribute generates no accessors, it will be warned
+ - If both 'isa' and 'does' are specified and 'isa' does not do
+ 'does', then it will be warned
* Mouse::Object
- Fix a possible segv which is caused by destructors (gfx)
* Mouse::Util::TypeConstraints
$attribute->create($metaclass, $attribute->name, %{$attribute});
}
+ if(!$attribute->{associated_methods} && ($attribute->{is} || '') ne 'bare'){
+ Carp::cluck(
+ 'Attribute (' . $attribute->name . ') of class ' . $metaclass->name
+ . ' has no associated methods (did you mean to provide an "is" argument?)');
+ }
+
return;
}
my $tc;
if(exists $args->{isa}){
- $args->{type_constraint} = Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint($args->{isa});
+ $tc = $args->{type_constraint} = Mouse::Util::TypeConstraints::find_or_create_isa_type_constraint($args->{isa});
}
- elsif(exists $args->{does}){
- $args->{type_constraint} = Mouse::Util::TypeConstraints::find_or_create_does_type_constraint($args->{does});
+
+ if(exists $args->{does}){
+ if(defined $tc){ # both isa and does supplied
+ my $does_ok = do{
+ local $@;
+ eval{ "$tc"->does($args) };
+ };
+ if(!$does_ok){
+ $class->throw_error("Cannot have both an isa option and a does option because '$tc' does not do '$args->{does}' on attribute ($name)");
+ }
+ }
+ else {
+ $tc = $args->{type_constraint} = Mouse::Util::TypeConstraints::find_or_create_does_type_constraint($args->{does});
+ }
}
- $tc = $args->{type_constraint};
if($args->{coerce}){
defined($tc)
# if isa and does appear together, then see if Class->does(Role)
# if it does work... then the does() check is actually not needed
# since the isa() check will imply the does() check
- has 'foo' => (is => 'rw', isa => 'Foo::Class', does => 'Foo::Role');
+ has 'foo' => (is => 'rw', isa => 'Foo::Class');
package Foo::Class;
use Mouse;
use Test::More;
use Mouse;
- local $TODO = 'setting both isa and does';
-
# if isa and does appear together, then see if Class->does(Role)
# if it does not,.. we have a conflict... so we die loudly
::dies_ok {
- has 'foo' => (isa => 'Foo::Class', does => 'Bar::Class');
+ has 'foo' => (is => 'rw', isa => 'Foo::Class', does => 'Bar::Class');
} '... cannot have a does() which is not done by the isa()';
}
use Test::More;
use Mouse;
- local $TODO = 'setting both isa and does';
-
# if isa and does appear together, then see if Class->does(Role)
# if it does not,.. we have a conflict... so we die loudly
::dies_ok {
- has 'foo' => (isa => 'Bling', does => 'Bar::Class');
+ has 'foo' => (is => 'rw', isa => 'Bling', does => 'Bar::Class');
} '... cannot have a isa() which is cannot does()';
}
return value;
}
+static void
+mouse_check_isa_does_does(pTHX_ SV* const klass, SV* const name, SV* const isa, SV* const does){
+ STRLEN len;
+ const char* const pv = SvPV_const(isa, len); /* need strigify */
+ bool does_ok;
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ SAVESPTR(ERRSV);
+ ERRSV = sv_newmortal();
+
+ PUSHMARK(SP);
+ EXTEND(SP, 2);
+ mPUSHp(pv, len);
+ PUSHs(does);
+ PUTBACK;
+
+ call_method("does", G_EVAL | G_SCALAR);
+
+ SPAGAIN;
+ does_ok = sv_true(POPs);
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ if(!does_ok){
+ mouse_throw_error(klass, NULL,
+ "Cannot have both an isa option and a does option"
+ "because '%"SVf"' does not do '%"SVf"' on attribute (%"SVf")",
+ isa, does, name
+ );
+ }
+}
+
MODULE = Mouse::Meta::Attribute PACKAGE = Mouse::Meta::Attribute
PROTOTYPES: DISABLE
tc = newSVsv(POPs);
PUTBACK;
}
- else if((svp = hv_fetchs(args, "does", FALSE))){
- SPAGAIN;
- PUSHMARK(SP);
- XPUSHs(*svp);
- PUTBACK;
- call_pv("Mouse::Util::TypeConstraints::find_or_create_does_type_constraint",
- G_SCALAR);
- SPAGAIN;
- tc = newSVsv(POPs);
- PUTBACK;
+ if((svp = hv_fetchs(args, "does", FALSE))){
+ /* check 'isa' does 'does' */
+ if(tc){
+ mouse_check_isa_does_does(aTHX_ klass, name, tc, *svp);
+ /* nothing to do */
+ }
+ else{
+ SPAGAIN;
+ PUSHMARK(SP);
+ XPUSHs(*svp);
+ PUTBACK;
+
+ call_pv("Mouse::Util::TypeConstraints::find_or_create_does_type_constraint",
+ G_SCALAR);
+ SPAGAIN;
+ tc = newSVsv(POPs);
+ PUTBACK;
+ }
}
if(tc){
(void)hv_stores(args, "type_constraint", tc);