Tweak doc changes for role_type & class_type
[gitmo/Moose.git] / lib / Moose / Util / TypeConstraints.pm
CommitLineData
a15dff8d 1
2package Moose::Util::TypeConstraints;
3
998a8a25 4use Carp ();
9e856c83 5use List::MoreUtils qw( all any );
9a63faba 6use Scalar::Util qw( blessed reftype );
e606ae5f 7use Moose::Exporter;
a15dff8d 8
d9b40005 9## --------------------------------------------------------
e85d2a5d 10# Prototyped subs must be predeclared because we have a
11# circular dependency with Moose::Meta::Attribute et. al.
12# so in case of us being use'd first the predeclaration
d9b40005 13# ensures the prototypes are in scope when consumers are
14# compiled.
15
d9b40005 16# dah sugah!
180899ed 17sub where (&);
18sub via (&);
19sub message (&);
d9b40005 20sub optimize_as (&);
4e36cf24 21sub inline_as (&);
d9b40005 22
d9b40005 23## --------------------------------------------------------
8c4acc60 24
1fa1a58d 25use Moose::Deprecated;
4e036ee4 26use Moose::Meta::TypeConstraint;
3726f905 27use Moose::Meta::TypeConstraint::Union;
0fbd4b0a 28use Moose::Meta::TypeConstraint::Parameterized;
7e4e1ad4 29use Moose::Meta::TypeConstraint::Parameterizable;
620db045 30use Moose::Meta::TypeConstraint::Class;
31use Moose::Meta::TypeConstraint::Role;
dabed765 32use Moose::Meta::TypeConstraint::Enum;
0a6bff54 33use Moose::Meta::TypeConstraint::DuckType;
2ca63f5d 34use Moose::Meta::TypeCoercion;
3726f905 35use Moose::Meta::TypeCoercion::Union;
22aed3c0 36use Moose::Meta::TypeConstraint::Registry;
4e036ee4 37
e606ae5f 38Moose::Exporter->setup_import_methods(
39 as_is => [
40 qw(
180899ed 41 type subtype class_type role_type maybe_type duck_type
7afaa906 42 as where message optimize_as inline_as
e606ae5f 43 coerce from via
0faea2a8 44 enum union
e606ae5f 45 find_type_constraint
0d29b772 46 register_type_constraint
47 match_on_type )
e606ae5f 48 ],
e606ae5f 49);
a15dff8d 50
d9b40005 51## --------------------------------------------------------
52## type registry and some useful functions for it
53## --------------------------------------------------------
54
22aed3c0 55my $REGISTRY = Moose::Meta::TypeConstraint::Registry->new;
587ae0d2 56
180899ed 57sub get_type_constraint_registry {$REGISTRY}
58sub list_all_type_constraints { keys %{ $REGISTRY->type_constraints } }
59
d9b40005 60sub export_type_constraints_as_functions {
61 my $pkg = caller();
62 no strict 'refs';
180899ed 63 foreach my $constraint ( keys %{ $REGISTRY->type_constraints } ) {
64 my $tc = $REGISTRY->get_type_constraint($constraint)
65 ->_compiled_type_constraint;
66 *{"${pkg}::${constraint}"}
67 = sub { $tc->( $_[0] ) ? 1 : undef }; # the undef is for compat
a0f8153d 68 }
d9b40005 69}
182134e8 70
0c015f1b 71sub create_type_constraint_union {
8ac5be59 72 _create_type_constraint_union(\@_);
182134e8 73}
a15dff8d 74
a46050ae 75sub create_named_type_constraint_union {
76 my $name = shift;
8ac5be59 77 _create_type_constraint_union($name, \@_);
78}
79
80sub _create_type_constraint_union {
81 my $name;
82 $name = shift if @_ > 1;
83 my @tcs = @{ shift() };
84
a46050ae 85 my @type_constraint_names;
86
8ac5be59 87 if ( scalar @tcs == 1 && _detect_type_constraint_union( $tcs[0] ) ) {
88 @type_constraint_names = _parse_type_constraint_union( $tcs[0] );
a46050ae 89 }
90 else {
8ac5be59 91 @type_constraint_names = @tcs;
a46050ae 92 }
93
94 ( scalar @type_constraint_names >= 2 )
95 || __PACKAGE__->_throw_error(
96 "You must pass in at least 2 type names to make a union");
97
98 my @type_constraints = map {
99 find_or_parse_type_constraint($_)
100 || __PACKAGE__->_throw_error(
101 "Could not locate type constraint ($_) for the union");
102 } @type_constraint_names;
103
104 my %options = (
105 type_constraints => \@type_constraints
106 );
107 $options{name} = $name if defined $name;
108
109 return Moose::Meta::TypeConstraint::Union->new(%options);
110}
111
112
0c015f1b 113sub create_parameterized_type_constraint {
d9b40005 114 my $type_constraint_name = shift;
180899ed 115 my ( $base_type, $type_parameter )
116 = _parse_parameterized_type_constraint($type_constraint_name);
e85d2a5d 117
180899ed 118 ( defined $base_type && defined $type_parameter )
119 || __PACKAGE__->_throw_error(
120 "Could not parse type name ($type_constraint_name) correctly");
e85d2a5d 121
180899ed 122 if ( $REGISTRY->has_type_constraint($base_type) ) {
90e78884 123 my $base_type_tc = $REGISTRY->get_type_constraint($base_type);
124 return _create_parameterized_type_constraint(
125 $base_type_tc,
126 $type_parameter
127 );
180899ed 128 }
129 else {
130 __PACKAGE__->_throw_error(
131 "Could not locate the base type ($base_type)");
90e78884 132 }
22aed3c0 133}
134
90e78884 135sub _create_parameterized_type_constraint {
136 my ( $base_type_tc, $type_parameter ) = @_;
137 if ( $base_type_tc->can('parameterize') ) {
138 return $base_type_tc->parameterize($type_parameter);
180899ed 139 }
140 else {
90e78884 141 return Moose::Meta::TypeConstraint::Parameterized->new(
180899ed 142 name => $base_type_tc->name . '[' . $type_parameter . ']',
90e78884 143 parent => $base_type_tc,
180899ed 144 type_parameter =>
145 find_or_create_isa_type_constraint($type_parameter),
90e78884 146 );
147 }
180899ed 148}
90e78884 149
4ab662d6 150#should we also support optimized checks?
0c015f1b 151sub create_class_type_constraint {
620db045 152 my ( $class, $options ) = @_;
153
180899ed 154# too early for this check
155#find_type_constraint("ClassName")->check($class)
156# || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
3fef8ce8 157
620db045 158 my %options = (
159 class => $class,
160 name => $class,
161 %{ $options || {} },
4ab662d6 162 );
620db045 163
164 $options{name} ||= "__ANON__";
165
180899ed 166 Moose::Meta::TypeConstraint::Class->new(%options);
3fef8ce8 167}
168
0c015f1b 169sub create_role_type_constraint {
620db045 170 my ( $role, $options ) = @_;
e85d2a5d 171
180899ed 172# too early for this check
173#find_type_constraint("ClassName")->check($class)
174# || __PACKAGE__->_throw_error("Can't create a class type constraint because '$class' is not a class name");
e85d2a5d 175
620db045 176 my %options = (
177 role => $role,
178 name => $role,
179 %{ $options || {} },
180 );
e85d2a5d 181
620db045 182 $options{name} ||= "__ANON__";
183
180899ed 184 Moose::Meta::TypeConstraint::Role->new(%options);
620db045 185}
186
0c015f1b 187sub find_or_create_type_constraint {
620db045 188 my ( $type_constraint_name, $options_for_anon_type ) = @_;
189
180899ed 190 if ( my $constraint
191 = find_or_parse_type_constraint($type_constraint_name) ) {
620db045 192 return $constraint;
d9b40005 193 }
620db045 194 elsif ( defined $options_for_anon_type ) {
180899ed 195
d9b40005 196 # NOTE:
4ab662d6 197 # if there is no $options_for_anon_type
198 # specified, then we assume they don't
f3c4e20e 199 # want to create one, and return nothing.
f3c4e20e 200
d9b40005 201 # otherwise assume that we should create
e85d2a5d 202 # an ANON type with the $options_for_anon_type
d9b40005 203 # options which can be passed in. It should
e85d2a5d 204 # be noted that these don't get registered
d9b40005 205 # so we need to return it.
206 # - SL
207 return Moose::Meta::TypeConstraint->new(
208 name => '__ANON__',
e85d2a5d 209 %{$options_for_anon_type}
d9b40005 210 );
211 }
e85d2a5d 212
620db045 213 return;
214}
215
0c015f1b 216sub find_or_create_isa_type_constraint {
620db045 217 my $type_constraint_name = shift;
180899ed 218 find_or_parse_type_constraint($type_constraint_name)
219 || create_class_type_constraint($type_constraint_name);
620db045 220}
221
0c015f1b 222sub find_or_create_does_type_constraint {
620db045 223 my $type_constraint_name = shift;
180899ed 224 find_or_parse_type_constraint($type_constraint_name)
225 || create_role_type_constraint($type_constraint_name);
620db045 226}
227
0c015f1b 228sub find_or_parse_type_constraint {
eb4c4e82 229 my $type_constraint_name = normalize_type_constraint_name(shift);
620db045 230 my $constraint;
180899ed 231
232 if ( $constraint = find_type_constraint($type_constraint_name) ) {
e606ae5f 233 return $constraint;
180899ed 234 }
235 elsif ( _detect_type_constraint_union($type_constraint_name) ) {
620db045 236 $constraint = create_type_constraint_union($type_constraint_name);
180899ed 237 }
238 elsif ( _detect_parameterized_type_constraint($type_constraint_name) ) {
239 $constraint
240 = create_parameterized_type_constraint($type_constraint_name);
241 }
242 else {
620db045 243 return;
244 }
bb6c8335 245
d9b40005 246 $REGISTRY->add_type_constraint($constraint);
e85d2a5d 247 return $constraint;
d9b40005 248}
22aed3c0 249
eb4c4e82 250sub normalize_type_constraint_name {
84a9c64c 251 my $type_constraint_name = shift;
c8f663b2 252 $type_constraint_name =~ s/\s//g;
eb4c4e82 253 return $type_constraint_name;
254}
255
5f223879 256sub _confess {
257 my $error = shift;
258
259 local $Carp::CarpLevel = $Carp::CarpLevel + 1;
260 Carp::confess($error);
261}
262
22aed3c0 263## --------------------------------------------------------
264## exported functions ...
265## --------------------------------------------------------
266
0c015f1b 267sub find_type_constraint {
eeedfc8a 268 my $type = shift;
269
270 if ( blessed $type and $type->isa("Moose::Meta::TypeConstraint") ) {
271 return $type;
e606ae5f 272 }
273 else {
274 return unless $REGISTRY->has_type_constraint($type);
eeedfc8a 275 return $REGISTRY->get_type_constraint($type);
276 }
277}
22aed3c0 278
0c015f1b 279sub register_type_constraint {
3fef8ce8 280 my $constraint = shift;
180899ed 281 __PACKAGE__->_throw_error("can't register an unnamed type constraint")
282 unless defined $constraint->name;
3fef8ce8 283 $REGISTRY->add_type_constraint($constraint);
dabed765 284 return $constraint;
3fef8ce8 285}
286
7c13858b 287# type constructors
a15dff8d 288
9c27968f 289sub type {
9e856c83 290 my $name = shift;
9a63faba 291
9e856c83 292 my %p = map { %{$_} } @_;
293
180899ed 294 return _create_type_constraint(
295 $name, undef, $p{where}, $p{message},
4e36cf24 296 $p{optimize_as}, $p{inline_as},
180899ed 297 );
a15dff8d 298}
299
9c27968f 300sub subtype {
180899ed 301 if ( @_ == 1 && !ref $_[0] ) {
302 __PACKAGE__->_throw_error(
303 'A subtype cannot consist solely of a name, it must have a parent'
304 );
f75f625d 305 }
306
f6c0c589 307 # The blessed check is mostly to accommodate MooseX::Types, which
308 # uses an object which overloads stringification as a type name.
180899ed 309 my $name = ref $_[0] && !blessed $_[0] ? undef : shift;
9a63faba 310
311 my %p = map { %{$_} } @_;
312
313 # subtype Str => where { ... };
180899ed 314 if ( !exists $p{as} ) {
9e856c83 315 $p{as} = $name;
9a63faba 316 $name = undef;
317 }
318
180899ed 319 return _create_type_constraint(
320 $name, $p{as}, $p{where}, $p{message},
4e36cf24 321 $p{optimize_as}, $p{inline_as},
180899ed 322 );
a15dff8d 323}
324
9c27968f 325sub class_type {
4ab662d6 326 register_type_constraint(
327 create_class_type_constraint(
328 $_[0],
180899ed 329 ( defined( $_[1] ) ? $_[1] : () ),
4ab662d6 330 )
331 );
3fef8ce8 332}
333
620db045 334sub role_type ($;$) {
335 register_type_constraint(
336 create_role_type_constraint(
337 $_[0],
180899ed 338 ( defined( $_[1] ) ? $_[1] : () ),
620db045 339 )
340 );
341}
342
1b2c9bda 343sub maybe_type {
344 my ($type_parameter) = @_;
345
28ce1444 346 register_type_constraint(
ed7060d9 347 $REGISTRY->get_type_constraint('Maybe')->parameterize($type_parameter)
28ce1444 348 );
1b2c9bda 349}
350
180899ed 351sub duck_type {
cdacfaf3 352 my ( $type_name, @methods ) = @_;
180899ed 353 if ( ref $type_name eq 'ARRAY' && !@methods ) {
cdacfaf3 354 @methods = @$type_name;
180899ed 355 $type_name = undef;
356 }
bce5d4a5 357 if ( @methods == 1 && ref $methods[0] eq 'ARRAY' ) {
358 @methods = @{ $methods[0] };
359 }
180899ed 360
361 register_type_constraint(
0a6bff54 362 create_duck_type_constraint(
cdacfaf3 363 $type_name,
0a6bff54 364 \@methods,
180899ed 365 )
366 );
367}
368
9c27968f 369sub coerce {
180899ed 370 my ( $type_name, @coercion_map ) = @_;
371 _install_type_coercions( $type_name, \@coercion_map );
182134e8 372}
373
f6c0c589 374# The trick of returning @_ lets us avoid having to specify a
375# prototype. Perl will parse this:
376#
377# subtype 'Foo'
378# => as 'Str'
379# => where { ... }
380#
381# as this:
382#
383# subtype( 'Foo', as( 'Str', where { ... } ) );
384#
69229b40 385# If as() returns all its extra arguments, this just works, and
f6c0c589 386# preserves backwards compatibility.
180899ed 387sub as { { as => shift }, @_ }
9e856c83 388sub where (&) { { where => $_[0] } }
389sub message (&) { { message => $_[0] } }
390sub optimize_as (&) { { optimize_as => $_[0] } }
4e36cf24 391sub inline_as (&) { { inline_as => $_[0] } }
8ecb1fa0 392
9a63faba 393sub from {@_}
394sub via (&) { $_[0] }
a15dff8d 395
9c27968f 396sub enum {
180899ed 397 my ( $type_name, @values ) = @_;
398
4ab662d6 399 # NOTE:
400 # if only an array-ref is passed then
9f4334a1 401 # you get an anon-enum
402 # - SL
f6af1028 403 if ( ref $type_name eq 'ARRAY' ) {
404 @values == 0
405 || __PACKAGE__->_throw_error("enum called with an array reference and additional arguments. Did you mean to parenthesize the enum call's parameters?");
406
9f4334a1 407 @values = @$type_name;
408 $type_name = undef;
409 }
bce5d4a5 410 if ( @values == 1 && ref $values[0] eq 'ARRAY' ) {
411 @values = @{ $values[0] };
412 }
dabed765 413
414 register_type_constraint(
415 create_enum_type_constraint(
416 $type_name,
417 \@values,
418 )
419 );
420}
421
0faea2a8 422sub union {
423 my ( $type_name, @constraints ) = @_;
424 if ( ref $type_name eq 'ARRAY' ) {
425 @constraints == 0
426 || __PACKAGE__->_throw_error("union called with an array reference and additional arguments.");
427 @constraints = @$type_name;
428 $type_name = undef;
429 }
430 if ( @constraints == 1 && ref $constraints[0] eq 'ARRAY' ) {
431 @constraints = @{ $constraints[0] };
432 }
0faea2a8 433 if ( defined $type_name ) {
a46050ae 434 return register_type_constraint(
435 create_named_type_constraint_union( $type_name, @constraints )
436 );
0faea2a8 437 }
a46050ae 438 return create_type_constraint_union( @constraints );
0faea2a8 439}
440
0c015f1b 441sub create_enum_type_constraint {
dabed765 442 my ( $type_name, $values ) = @_;
e606ae5f 443
dabed765 444 Moose::Meta::TypeConstraint::Enum->new(
180899ed 445 name => $type_name || '__ANON__',
dabed765 446 values => $values,
a0f8153d 447 );
fcec2383 448}
449
0a6bff54 450sub create_duck_type_constraint {
451 my ( $type_name, $methods ) = @_;
452
453 Moose::Meta::TypeConstraint::DuckType->new(
454 name => $type_name || '__ANON__',
455 methods => $methods,
456 );
457}
458
0d29b772 459sub match_on_type {
460 my ($to_match, @cases) = @_;
461 my $default;
462 if (@cases % 2 != 0) {
463 $default = pop @cases;
464 (ref $default eq 'CODE')
465 || __PACKAGE__->_throw_error("Default case must be a CODE ref, not $default");
466 }
467 while (@cases) {
468 my ($type, $action) = splice @cases, 0, 2;
469
470 unless (blessed $type && $type->isa('Moose::Meta::TypeConstraint')) {
471 $type = find_or_parse_type_constraint($type)
472 || __PACKAGE__->_throw_error("Cannot find or parse the type '$type'")
473 }
474
475 (ref $action eq 'CODE')
476 || __PACKAGE__->_throw_error("Match action must be a CODE ref, not $action");
477
478 if ($type->check($to_match)) {
479 local $_ = $to_match;
480 return $action->($to_match);
481 }
482 }
1d39d709 483 (defined $default)
484 || __PACKAGE__->_throw_error("No cases matched for $to_match");
0d29b772 485 {
486 local $_ = $to_match;
1d39d709 487 return $default->($to_match);
0d29b772 488 }
489}
490
491
d9b40005 492## --------------------------------------------------------
493## desugaring functions ...
494## --------------------------------------------------------
495
e85d2a5d 496sub _create_type_constraint ($$$;$$) {
9a63faba 497 my $name = shift;
498 my $parent = shift;
499 my $check = shift;
500 my $message = shift;
501 my $optimized = shift;
4e36cf24 502 my $inlined = shift;
d9b40005 503
9a63faba 504 my $pkg_defined_in = scalar( caller(1) );
e85d2a5d 505
1da6728b 506 if ( defined $name ) {
d9b40005 507 my $type = $REGISTRY->get_type_constraint($name);
e85d2a5d 508
5f223879 509 ( $type->_package_defined_in eq $pkg_defined_in )
510 || _confess(
511 "The type constraint '$name' has already been created in "
512 . $type->_package_defined_in
513 . " and cannot be created again in "
514 . $pkg_defined_in )
515 if defined $type;
eee1a213 516
517 $name =~ /^[\w:\.]+$/
518 or die qq{$name contains invalid characters for a type name.}
33c8a6d0 519 . qq{ Names can contain alphanumeric character, ":", and "."\n};
e85d2a5d 520 }
1da6728b 521
9ceb576e 522 my %opts = (
9a63faba 523 name => $name,
d9b40005 524 package_defined_in => $pkg_defined_in,
e85d2a5d 525
1da6728b 526 ( $check ? ( constraint => $check ) : () ),
527 ( $message ? ( message => $message ) : () ),
528 ( $optimized ? ( optimized => $optimized ) : () ),
4e36cf24 529 ( $inlined ? ( inlined => $inlined ) : () ),
d9b40005 530 );
1da6728b 531
9ceb576e 532 my $constraint;
180899ed 533 if (
534 defined $parent
1da6728b 535 and $parent
180899ed 536 = blessed $parent
537 ? $parent
538 : find_or_create_isa_type_constraint($parent)
539 ) {
85a9908f 540 $constraint = $parent->create_child_type(%opts);
1da6728b 541 }
542 else {
543 $constraint = Moose::Meta::TypeConstraint->new(%opts);
4ab662d6 544 }
d9b40005 545
546 $REGISTRY->add_type_constraint($constraint)
547 if defined $name;
548
549 return $constraint;
550}
551
e85d2a5d 552sub _install_type_coercions ($$) {
180899ed 553 my ( $type_name, $coercion_map ) = @_;
e606ae5f 554 my $type = find_type_constraint($type_name);
180899ed 555 ( defined $type )
556 || __PACKAGE__->_throw_error(
a885c019 557 "Cannot find type '$type_name', perhaps you forgot to load it");
180899ed 558 if ( $type->has_coercion ) {
41e007e4 559 $type->coercion->add_type_coercions(@$coercion_map);
560 }
561 else {
562 my $type_coercion = Moose::Meta::TypeCoercion->new(
563 type_coercion_map => $coercion_map,
564 type_constraint => $type
565 );
566 $type->coercion($type_coercion);
567 }
d9b40005 568}
569
570## --------------------------------------------------------
f1917f58 571## type notation parsing ...
572## --------------------------------------------------------
573
574{
180899ed 575
e85d2a5d 576 # All I have to say is mugwump++ cause I know
577 # do not even have enough regexp-fu to be able
578 # to have written this (I can only barely
f1917f58 579 # understand it as it is)
e85d2a5d 580 # - SL
581
f1917f58 582 use re "eval";
583
eee1a213 584 my $valid_chars = qr{[\w:\.]};
68d5a469 585 my $type_atom = qr{ (?>$valid_chars+) }x;
68113f48 586 my $ws = qr{ (?>\s*) }x;
587 my $op_union = qr{ $ws \| $ws }x;
588
589 my ($type, $type_capture_parts, $type_with_parameter, $union, $any);
590 if (Class::MOP::IS_RUNNING_ON_5_10) {
591 my $type_pattern
592 = q{ (?&type_atom) (?: \[ (?&ws) (?&any) (?&ws) \] )? };
593 my $type_capture_parts_pattern
594 = q{ ((?&type_atom)) (?: \[ (?&ws) ((?&any)) (?&ws) \] )? };
595 my $type_with_parameter_pattern
596 = q{ (?&type_atom) \[ (?&ws) (?&any) (?&ws) \] };
597 my $union_pattern
598 = q{ (?&type) (?> (?: (?&op_union) (?&type) )+ ) };
599 my $any_pattern
600 = q{ (?&type) | (?&union) };
601
602 my $defines = qr{(?(DEFINE)
603 (?<valid_chars> $valid_chars)
604 (?<type_atom> $type_atom)
605 (?<ws> $ws)
606 (?<op_union> $op_union)
607 (?<type> $type_pattern)
608 (?<type_capture_parts> $type_capture_parts_pattern)
609 (?<type_with_parameter> $type_with_parameter_pattern)
610 (?<union> $union_pattern)
611 (?<any> $any_pattern)
612 )}x;
613
614 $type = qr{ $type_pattern $defines }x;
615 $type_capture_parts = qr{ $type_capture_parts_pattern $defines }x;
616 $type_with_parameter = qr{ $type_with_parameter_pattern $defines }x;
617 $union = qr{ $union_pattern $defines }x;
618 $any = qr{ $any_pattern $defines }x;
619 }
620 else {
621 $type
622 = qr{ $type_atom (?: \[ $ws (??{$any}) $ws \] )? }x;
623 $type_capture_parts
624 = qr{ ($type_atom) (?: \[ $ws ((??{$any})) $ws \] )? }x;
625 $type_with_parameter
626 = qr{ $type_atom \[ $ws (??{$any}) $ws \] }x;
627 $union
628 = qr{ $type (?> (?: $op_union $type )+ ) }x;
629 $any
630 = qr{ $type | $union }x;
631 }
f1917f58 632
f1917f58 633
0fbd4b0a 634 sub _parse_parameterized_type_constraint {
180899ed 635 { no warnings 'void'; $any; } # force capture of interpolated lexical
84a9c64c 636 $_[0] =~ m{ $type_capture_parts }x;
180899ed 637 return ( $1, $2 );
f1917f58 638 }
639
0fbd4b0a 640 sub _detect_parameterized_type_constraint {
180899ed 641 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 642 $_[0] =~ m{ ^ $type_with_parameter $ }x;
f1917f58 643 }
644
645 sub _parse_type_constraint_union {
180899ed 646 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 647 my $given = shift;
648 my @rv;
649 while ( $given =~ m{ \G (?: $op_union )? ($type) }gcx ) {
82a5b1a7 650 push @rv => $1;
e85d2a5d 651 }
180899ed 652 ( pos($given) eq length($given) )
653 || __PACKAGE__->_throw_error( "'$given' didn't parse (parse-pos="
654 . pos($given)
655 . " and str-length="
656 . length($given)
657 . ")" );
e85d2a5d 658 @rv;
f1917f58 659 }
660
661 sub _detect_type_constraint_union {
180899ed 662 { no warnings 'void'; $any; } # force capture of interpolated lexical
e85d2a5d 663 $_[0] =~ m{^ $type $op_union $type ( $op_union .* )? $}x;
f1917f58 664 }
665}
666
667## --------------------------------------------------------
d9b40005 668# define some basic built-in types
669## --------------------------------------------------------
a15dff8d 670
06d02aac 671# By making these classes immutable before creating all the types in
672# Moose::Util::TypeConstraints::Builtin , we avoid repeatedly calling the slow
673# MOP-based accessors.
3cae4250 674$_->make_immutable(
675 inline_constructor => 1,
676 constructor_name => "_new",
677
678 # these are Class::MOP accessors, so they need inlining
679 inline_accessors => 1
680 ) for grep { $_->is_mutable }
37edf27e 681 map { Class::MOP::class_of($_) }
3cae4250 682 qw(
683 Moose::Meta::TypeConstraint
684 Moose::Meta::TypeConstraint::Union
685 Moose::Meta::TypeConstraint::Parameterized
686 Moose::Meta::TypeConstraint::Parameterizable
687 Moose::Meta::TypeConstraint::Class
688 Moose::Meta::TypeConstraint::Role
689 Moose::Meta::TypeConstraint::Enum
0a6bff54 690 Moose::Meta::TypeConstraint::DuckType
3cae4250 691 Moose::Meta::TypeConstraint::Registry
692);
693
06d02aac 694require Moose::Util::TypeConstraints::Builtins;
695Moose::Util::TypeConstraints::Builtins::define_builtins($REGISTRY);
7e4e1ad4 696
180899ed 697my @PARAMETERIZABLE_TYPES
2c29c0e7 698 = map { $REGISTRY->get_type_constraint($_) } qw[ScalarRef ArrayRef HashRef Maybe];
180899ed 699
700sub get_all_parameterizable_types {@PARAMETERIZABLE_TYPES}
7e4e1ad4 701
4ab662d6 702sub add_parameterizable_type {
7e4e1ad4 703 my $type = shift;
180899ed 704 ( blessed $type
705 && $type->isa('Moose::Meta::TypeConstraint::Parameterizable') )
706 || __PACKAGE__->_throw_error(
707 "Type must be a Moose::Meta::TypeConstraint::Parameterizable not $type"
708 );
7e4e1ad4 709 push @PARAMETERIZABLE_TYPES => $type;
4ab662d6 710}
7e4e1ad4 711
712## --------------------------------------------------------
d9b40005 713# end of built-in types ...
714## --------------------------------------------------------
715
943596a6 716{
717 my @BUILTINS = list_all_type_constraints();
180899ed 718 sub list_all_builtin_type_constraints {@BUILTINS}
943596a6 719}
720
6ea98933 721sub _throw_error {
6b83828f 722 shift;
6ea98933 723 require Moose;
724 unshift @_, 'Moose';
725 goto &Moose::throw_error;
726}
727
a15dff8d 7281;
729
ad46f524 730# ABSTRACT: Type constraint system for Moose
731
a15dff8d 732__END__
733
734=pod
735
a15dff8d 736=head1 SYNOPSIS
737
738 use Moose::Util::TypeConstraints;
739
04eec387 740 subtype 'Natural',
741 as 'Int',
742 where { $_ > 0 };
e85d2a5d 743
04eec387 744 subtype 'NaturalLessThanTen',
745 as 'Natural',
746 where { $_ < 10 },
747 message { "This number ($_) is not less than ten!" };
e85d2a5d 748
04eec387 749 coerce 'Num',
750 from 'Str',
751 via { 0+$_ };
e85d2a5d 752
5f369d33 753 class_type 'DateTimeClass', { class => 'DateTime' };
7605e87a 754
755 role_type 'Barks', { role => 'Some::Library::Role::Barks' };
756
04eec387 757 enum 'RGBColors', [qw(red green blue)];
a15dff8d 758
74dccf76 759 union 'StringOrArray', [qw( String Array )];
760
e7fcb7b2 761 no Moose::Util::TypeConstraints;
762
a15dff8d 763=head1 DESCRIPTION
764
e85d2a5d 765This module provides Moose with the ability to create custom type
6549b0d1 766constraints to be used in attribute definition.
e522431d 767
6ba6d68c 768=head2 Important Caveat
769
e85d2a5d 770This is B<NOT> a type system for Perl 5. These are type constraints,
771and they are not used by Moose unless you tell it to. No type
e7fcb7b2 772inference is performed, expressions are not typed, etc. etc. etc.
6ba6d68c 773
e7fcb7b2 774A type constraint is at heart a small "check if a value is valid"
775function. A constraint can be associated with an attribute. This
776simplifies parameter validation, and makes your code clearer to read,
777because you can refer to constraints by name.
6ba6d68c 778
2c0cbef7 779=head2 Slightly Less Important Caveat
780
e7fcb7b2 781It is B<always> a good idea to quote your type names.
004222dc 782
e7fcb7b2 783This prevents Perl from trying to execute the call as an indirect
784object call. This can be an issue when you have a subtype with the
785same name as a valid class.
2c0cbef7 786
e7fcb7b2 787For instance:
e85d2a5d 788
2c0cbef7 789 subtype DateTime => as Object => where { $_->isa('DateTime') };
790
e7fcb7b2 791will I<just work>, while this:
2c0cbef7 792
793 use DateTime;
794 subtype DateTime => as Object => where { $_->isa('DateTime') };
795
e85d2a5d 796will fail silently and cause many headaches. The simple way to solve
797this, as well as future proof your subtypes from classes which have
e7fcb7b2 798yet to have been created, is to quote the type name:
2c0cbef7 799
800 use DateTime;
04eec387 801 subtype 'DateTime', as 'Object', where { $_->isa('DateTime') };
2c0cbef7 802
6ba6d68c 803=head2 Default Type Constraints
e522431d 804
e606ae5f 805This module also provides a simple hierarchy for Perl 5 types, here is
004222dc 806that hierarchy represented visually.
e522431d 807
808 Any
e85d2a5d 809 Item
5a4c5493 810 Bool
7e4e1ad4 811 Maybe[`a]
f65cb534 812 Undef
813 Defined
5a4c5493 814 Value
5a4c5493 815 Str
f1bbe1e1 816 Num
817 Int
fcb5b0cd 818 ClassName
819 RoleName
5a4c5493 820 Ref
2c29c0e7 821 ScalarRef[`a]
7e4e1ad4 822 ArrayRef[`a]
823 HashRef[`a]
5a4c5493 824 CodeRef
825 RegexpRef
3f7376b0 826 GlobRef
94ab1609 827 FileHandle
e85d2a5d 828 Object
e522431d 829
4ab662d6 830B<NOTE:> Any type followed by a type parameter C<[`a]> can be
7e4e1ad4 831parameterized, this means you can say:
832
757e07ef 833 ArrayRef[Int] # an array of integers
7e4e1ad4 834 HashRef[CodeRef] # a hash of str to CODE ref mappings
2c29c0e7 835 ScalarRef[Int] # a reference to an integer
7e4e1ad4 836 Maybe[Str] # value may be a string, may be undefined
837
4e8a0f64 838If Moose finds a name in brackets that it does not recognize as an
839existing type, it assumes that this is a class name, for example
840C<ArrayRef[DateTime]>.
841
e7fcb7b2 842B<NOTE:> Unless you parameterize a type, then it is invalid to include
843the square brackets. I.e. C<ArrayRef[]> will be treated as a new type
844name, I<not> as a parameterization of C<ArrayRef>.
e606ae5f 845
4ab662d6 846B<NOTE:> The C<Undef> type constraint for the most part works
847correctly now, but edge cases may still exist, please use it
6549b0d1 848sparingly.
703e92fb 849
7e4e1ad4 850B<NOTE:> The C<ClassName> type constraint does a complex package
e7fcb7b2 851existence check. This means that your class B<must> be loaded for this
852type constraint to pass.
9af1d28b 853
e7fcb7b2 854B<NOTE:> The C<RoleName> constraint checks a string is a I<package
4831e2de 855name> which is a role, like C<'MyApp::Role::Comparable'>.
ed87d4fd 856
e606ae5f 857=head2 Type Constraint Naming
004222dc 858
eee1a213 859Type name declared via this module can only contain alphanumeric
860characters, colons (:), and periods (.).
861
e606ae5f 862Since the types created by this module are global, it is suggested
863that you namespace your types just as you would namespace your
e7fcb7b2 864modules. So instead of creating a I<Color> type for your
865B<My::Graphics> module, you would call the type
866I<My::Graphics::Types::Color> instead.
004222dc 867
703e92fb 868=head2 Use with Other Constraint Modules
869
e7fcb7b2 870This module can play nicely with other constraint modules with some
871slight tweaking. The C<where> clause in types is expected to be a
69229b40 872C<CODE> reference which checks its first argument and returns a
e7fcb7b2 873boolean. Since most constraint modules work in a similar way, it
874should be simple to adapt them to work with Moose.
703e92fb 875
e85d2a5d 876For instance, this is how you could use it with
877L<Declare::Constraints::Simple> to declare a completely new type.
703e92fb 878
9e856c83 879 type 'HashOfArrayOfObjects',
04eec387 880 where {
881 IsHashRef(
882 -keys => HasLength,
883 -values => IsArrayRef(IsObject)
884 )->(@_);
885 };
703e92fb 886
2c739d1a 887For more examples see the F<t/examples/example_w_DCS.t> test
e7fcb7b2 888file.
703e92fb 889
69229b40 890Here is an example of using L<Test::Deep> and its non-test
e85d2a5d 891related C<eq_deeply> function.
703e92fb 892
04eec387 893 type 'ArrayOfHashOfBarsAndRandomNumbers',
894 where {
e85d2a5d 895 eq_deeply($_,
703e92fb 896 array_each(subhashof({
897 bar => isa('Bar'),
898 random_number => ignore()
e85d2a5d 899 })))
703e92fb 900 };
901
e606ae5f 902For a complete example see the
2c739d1a 903F<t/examples/example_w_TestDeep.t> test file.
e85d2a5d 904
32549612 905=head2 Error messages
906
907Type constraints can also specify custom error messages, for when they fail to
908validate. This is provided as just another coderef, which receives the invalid
909value in C<$_>, as in:
910
911 subtype 'PositiveInt',
912 as 'Int',
913 where { $_ > 0 },
914 message { "$_ is not a positive integer!" };
915
916If no message is specified, a default message will be used, which indicates
917which type constraint was being used and what value failed. If
918L<Devel::PartialDump> (version 0.14 or higher) is installed, it will be used to
919display the invalid value, otherwise it will just be printed as is.
920
a15dff8d 921=head1 FUNCTIONS
922
923=head2 Type Constraint Constructors
924
e7fcb7b2 925The following functions are used to create type constraints. They
926will also register the type constraints your create in a global
927registry that is used to look types up by name.
a15dff8d 928
cec39889 929See the L</SYNOPSIS> for an example of how to use these.
a15dff8d 930
6ba6d68c 931=over 4
a15dff8d 932
04eec387 933=item B<< subtype 'Name', as 'Parent', where { } ... >>
182134e8 934
e85d2a5d 935This creates a named subtype.
d6e2d9a1 936
dba9208a 937If you provide a parent that Moose does not recognize, it will
938automatically create a new class type constraint for this name.
939
9e856c83 940When creating a named type, the C<subtype> function should either be
941called with the sugar helpers (C<where>, C<message>, etc), or with a
942name and a hashref of parameters:
943
944 subtype( 'Foo', { where => ..., message => ... } );
945
946The valid hashref keys are C<as> (the parent), C<where>, C<message>,
947and C<optimize_as>.
9a63faba 948
04eec387 949=item B<< subtype as 'Parent', where { } ... >>
182134e8 950
e85d2a5d 951This creates an unnamed subtype and will return the type
952constraint meta-object, which will be an instance of
953L<Moose::Meta::TypeConstraint>.
a15dff8d 954
9e856c83 955When creating an anonymous type, the C<subtype> function should either
956be called with the sugar helpers (C<where>, C<message>, etc), or with
957just a hashref of parameters:
958
959 subtype( { where => ..., message => ... } );
960
620db045 961=item B<class_type ($class, ?$options)>
3fef8ce8 962
ed87d4fd 963Creates a new subtype of C<Object> with the name C<$class> and the
964metaclass L<Moose::Meta::TypeConstraint::Class>.
3fef8ce8 965
7605e87a 966 # Create a type called 'Box' which tests for objects which ->isa('Box')
967 class_type 'Box';
968
5f369d33 969By default, the name of the type and the name of the class are the same, but
970you can specify both separately.
7605e87a 971
972 # Create a type called 'Box' which tests for objects which ->isa('ObjectLibrary::Box');
973 class_type 'Box', { class => 'ObjectLibrary::Box' };
974
620db045 975=item B<role_type ($role, ?$options)>
976
ed87d4fd 977Creates a C<Role> type constraint with the name C<$role> and the
978metaclass L<Moose::Meta::TypeConstraint::Role>.
620db045 979
7605e87a 980 # Create a type called 'Walks' which tests for objects which ->does('Walks')
981 role_type 'Walks';
982
5f369d33 983By default, the name of the type and the name of the role are the same, but
984you can specify both separately.
7605e87a 985
986 # Create a type called 'Walks' which tests for objects which ->does('MooseX::Role::Walks');
987 role_type 'Walks', { role => 'MooseX::Role::Walks' };
988
1b2c9bda 989=item B<maybe_type ($type)>
990
991Creates a type constraint for either C<undef> or something of the
992given type.
993
bce5d4a5 994=item B<duck_type ($name, \@methods)>
e451e855 995
88b68372 996This will create a subtype of Object and test to make sure the value
bce5d4a5 997C<can()> do the methods in C<\@methods>.
88b68372 998
999This is intended as an easy way to accept non-Moose objects that
1000provide a certain interface. If you're using Moose classes, we
1001recommend that you use a C<requires>-only Role instead.
e451e855 1002
1003=item B<duck_type (\@methods)>
1004
bce5d4a5 1005If passed an ARRAY reference as the only parameter instead of the
1006C<$name>, C<\@methods> pair, this will create an unnamed duck type.
1007This can be used in an attribute definition like so:
e451e855 1008
88b68372 1009 has 'cache' => (
1010 is => 'ro',
1011 isa => duck_type( [qw( get_set )] ),
1012 );
e451e855 1013
bce5d4a5 1014=item B<enum ($name, \@values)>
fcec2383 1015
e85d2a5d 1016This will create a basic subtype for a given set of strings.
1017The resulting constraint will be a subtype of C<Str> and
bce5d4a5 1018will match any of the items in C<\@values>. It is case sensitive.
cec39889 1019See the L</SYNOPSIS> for a simple example.
2c0cbef7 1020
6549b0d1 1021B<NOTE:> This is not a true proper enum type, it is simply
1022a convenient constraint builder.
2c0cbef7 1023
9f4334a1 1024=item B<enum (\@values)>
1025
bce5d4a5 1026If passed an ARRAY reference as the only parameter instead of the
1027C<$name>, C<\@values> pair, this will create an unnamed enum. This
1028can then be used in an attribute definition like so:
9f4334a1 1029
1030 has 'sort_order' => (
1031 is => 'ro',
4ab662d6 1032 isa => enum([qw[ ascending descending ]]),
9f4334a1 1033 );
1034
74dccf76 1035=item B<union ($name, \@constraints)>
1036
1037This will create a basic subtype where any of the provided constraints
1038may match in order to satisfy this constraint.
1039
1040=item B<union (\@constraints)>
1041
1042If passed an ARRAY reference as the only parameter instead of the
1043C<$name>, C<\@constraints> pair, this will create an unnamed union.
1044This can then be used in an attribute definition like so:
1045
1046 has 'items' => (
1047 is => 'ro',
1048 isa => union([qw[ Str ArrayRef ]]),
1049 );
1050
1051This is similar to the existing string union:
1052
1053 isa => 'Str|ArrayRef'
1054
1055except that it supports anonymous elements as child constraints:
1056
1057 has 'color' => (
1058 isa => 'ro',
1059 isa => union([ 'Int', enum([qw[ red green blue ]]) ]),
1060 );
1061
e7fcb7b2 1062=item B<as 'Parent'>
a15dff8d 1063
6ba6d68c 1064This is just sugar for the type constraint construction syntax.
a15dff8d 1065
e7fcb7b2 1066It takes a single argument, which is the name of a parent type.
1067
1068=item B<where { ... }>
a15dff8d 1069
6ba6d68c 1070This is just sugar for the type constraint construction syntax.
76d37e5a 1071
e7fcb7b2 1072It takes a subroutine reference as an argument. When the type
1073constraint is tested, the reference is run with the value to be tested
1074in C<$_>. This reference should return true or false to indicate
1075whether or not the constraint check passed.
e606ae5f 1076
e7fcb7b2 1077=item B<message { ... }>
76d37e5a 1078
1079This is just sugar for the type constraint construction syntax.
a15dff8d 1080
e7fcb7b2 1081It takes a subroutine reference as an argument. When the type
1082constraint fails, then the code block is run with the value provided
1083in C<$_>. This reference should return a string, which will be used in
1084the text of the exception thrown.
e606ae5f 1085
7142d232 1086=item B<inline_as { ... }>
1087
1088This can be used to define a "hand optimized" inlinable version of your type
1089constraint.
1090
1091You provide a subroutine which will be called I<as a method> on a
1092L<Moose::Meta::TypeConstraint> object. It will receive a single parameter, the
1093name of the variable to check, typically something like C<"$_"> or C<"$_[0]">.
1094
1095The subroutine should return a code string suitable for inlining. You can
297899d1 1096assume that the check will be wrapped in parentheses when it is inlined.
7142d232 1097
01062d8a 1098The inlined code should include any checks that your type's parent types
0578d5ce 1099do. For example, the C<Value> type's inlining sub looks like this:
7142d232 1100
1101 sub {
0578d5ce 1102 'defined(' . $_[1] . ')'
1103 . ' && !ref(' . $_[1] . ')'
7142d232 1104 }
1105
0578d5ce 1106Note that it checks if the variable is defined, since it is a subtype of
1107the C<Defined> type. However, to avoid repeating code, this can be optimized as:
1108
1109 sub {
1110 $_[0]->parent()->_inline_check($_[1])
1111 . ' && !ref(' . $_[1] . ')'
1112 }
7142d232 1113
e7fcb7b2 1114=item B<optimize_as { ... }>
8ecb1fa0 1115
7142d232 1116B<This feature is deprecated, use C<inline_as> instead.>
1117
e85d2a5d 1118This can be used to define a "hand optimized" version of your
d44714be 1119type constraint which can be used to avoid traversing a subtype
6549b0d1 1120constraint hierarchy.
d44714be 1121
b0f8f0ec 1122B<NOTE:> You should only use this if you know what you are doing.
1123All the built in types use this, so your subtypes (assuming they
d44714be 1124are shallow) will not likely need to use this.
1125
04eec387 1126=item B<< type 'Name', where { } ... >>
e7fcb7b2 1127
1128This creates a base type, which has no parent.
1129
1130The C<type> function should either be called with the sugar helpers
1131(C<where>, C<message>, etc), or with a name and a hashref of
1132parameters:
1133
1134 type( 'Foo', { where => ..., message => ... } );
1135
7142d232 1136The valid hashref keys are C<where>, C<message>, and C<inlined_as>.
e7fcb7b2 1137
6ba6d68c 1138=back
a15dff8d 1139
0d29b772 1140=head2 Type Constraint Utilities
1141
1142=over 4
1143
1144=item B<< match_on_type $value => ( $type => \&action, ... ?\&default ) >>
1145
1a15f4a8 1146This is a utility function for doing simple type based dispatching similar to
2ae1457e 1147match/case in OCaml and case/of in Haskell. It is not as featureful as those
1a15f4a8 1148languages, nor does not it support any kind of automatic destructuring
1149bind. Here is a simple Perl pretty printer dispatching over the core Moose
1150types.
0d29b772 1151
1152 sub ppprint {
1153 my $x = shift;
1a15f4a8 1154 match_on_type $x => (
1155 HashRef => sub {
0d29b772 1156 my $hash = shift;
1a15f4a8 1157 '{ '
1158 . (
1159 join ", " => map { $_ . ' => ' . ppprint( $hash->{$_} ) }
1160 sort keys %$hash
1161 ) . ' }';
1162 },
1163 ArrayRef => sub {
0d29b772 1164 my $array = shift;
1a15f4a8 1165 '[ ' . ( join ", " => map { ppprint($_) } @$array ) . ' ]';
1166 },
1167 CodeRef => sub {'sub { ... }'},
1168 RegexpRef => sub { 'qr/' . $_ . '/' },
1169 GlobRef => sub { '*' . B::svref_2object($_)->NAME },
0d29b772 1170 Object => sub { $_->can('to_string') ? $_->to_string : $_ },
1a15f4a8 1171 ScalarRef => sub { '\\' . ppprint( ${$_} ) },
1172 Num => sub {$_},
1173 Str => sub { '"' . $_ . '"' },
1174 Undef => sub {'undef'},
1175 => sub { die "I don't know what $_ is" }
1176 );
0d29b772 1177 }
1178
e7597637 1179Or a simple JSON serializer:
1180
1181 sub to_json {
1182 my $x = shift;
1a15f4a8 1183 match_on_type $x => (
1184 HashRef => sub {
e7597637 1185 my $hash = shift;
1a15f4a8 1186 '{ '
1187 . (
1188 join ", " =>
1189 map { '"' . $_ . '" : ' . to_json( $hash->{$_} ) }
1190 sort keys %$hash
1191 ) . ' }';
1192 },
1193 ArrayRef => sub {
e7597637 1194 my $array = shift;
1a15f4a8 1195 '[ ' . ( join ", " => map { to_json($_) } @$array ) . ' ]';
1196 },
1197 Num => sub {$_},
1198 Str => sub { '"' . $_ . '"' },
1199 Undef => sub {'null'},
1200 => sub { die "$_ is not acceptable json type" }
1201 );
e7597637 1202 }
1203
1a15f4a8 1204The matcher is done by mapping a C<$type> to an C<\&action>. The C<$type> can
1205be either a string type or a L<Moose::Meta::TypeConstraint> object, and
1206C<\&action> is a subroutine reference. This function will dispatch on the
1207first match for C<$value>. It is possible to have a catch-all by providing an
1208additional subroutine reference as the final argument to C<match_on_type>.
0d29b772 1209
1210=back
1211
6ba6d68c 1212=head2 Type Coercion Constructors
a15dff8d 1213
e7fcb7b2 1214You can define coercions for type constraints, which allow you to
1215automatically transform values to something valid for the type
1216constraint. If you ask your accessor to coerce, then Moose will run
1217the type-coercion code first, followed by the type constraint
1218check. This feature should be used carefully as it is very powerful
1219and could easily take off a limb if you are not careful.
a15dff8d 1220
cec39889 1221See the L</SYNOPSIS> for an example of how to use these.
a15dff8d 1222
6ba6d68c 1223=over 4
a15dff8d 1224
04eec387 1225=item B<< coerce 'Name', from 'OtherName', via { ... } >>
a15dff8d 1226
e7fcb7b2 1227This defines a coercion from one type to another. The C<Name> argument
1228is the type you are coercing I<to>.
1229
f55dd47f 1230To define multiple coercions, supply more sets of from/via pairs:
1231
04eec387 1232 coerce 'Name',
1233 from 'OtherName', via { ... },
1234 from 'ThirdName', via { ... };
f55dd47f 1235
e7fcb7b2 1236=item B<from 'OtherName'>
a15dff8d 1237
6ba6d68c 1238This is just sugar for the type coercion construction syntax.
1239
e7fcb7b2 1240It takes a single type name (or type object), which is the type being
1241coerced I<from>.
1242
1243=item B<via { ... }>
a15dff8d 1244
6ba6d68c 1245This is just sugar for the type coercion construction syntax.
a15dff8d 1246
e7fcb7b2 1247It takes a subroutine reference. This reference will be called with
1248the value to be coerced in C<$_>. It is expected to return a new value
1249of the proper type for the coercion.
1250
a15dff8d 1251=back
1252
e7fcb7b2 1253=head2 Creating and Finding Type Constraints
1254
1255These are additional functions for creating and finding type
1256constraints. Most of these functions are not available for
1257importing. The ones that are importable as specified.
004222dc 1258
1259=over 4
1260
e7fcb7b2 1261=item B<find_type_constraint($type_name)>
eb4c4e82 1262
e7fcb7b2 1263This function can be used to locate the L<Moose::Meta::TypeConstraint>
1264object for a named type.
eb4c4e82 1265
e7fcb7b2 1266This function is importable.
004222dc 1267
e7fcb7b2 1268=item B<register_type_constraint($type_object)>
004222dc 1269
e7fcb7b2 1270This function will register a L<Moose::Meta::TypeConstraint> with the
1271global type registry.
004222dc 1272
e7fcb7b2 1273This function is importable.
004222dc 1274
e7fcb7b2 1275=item B<normalize_type_constraint_name($type_constraint_name)>
004222dc 1276
e7fcb7b2 1277This method takes a type constraint name and returns the normalized
1278form. This removes any whitespace in the string.
004222dc 1279
e7fcb7b2 1280=item B<create_type_constraint_union($pipe_separated_types | @type_constraint_names)>
004222dc 1281
2dae61ad 1282=item B<create_named_type_constraint_union($name, $pipe_separated_types | @type_constraint_names)>
1283
e7fcb7b2 1284This can take a union type specification like C<'Int|ArrayRef[Int]'>,
1285or a list of names. It returns a new
1286L<Moose::Meta::TypeConstraint::Union> object.
004222dc 1287
e7fcb7b2 1288=item B<create_parameterized_type_constraint($type_name)>
620db045 1289
e7fcb7b2 1290Given a C<$type_name> in the form of C<'BaseType[ContainerType]'>,
1291this will create a new L<Moose::Meta::TypeConstraint::Parameterized>
1292object. The C<BaseType> must exist already exist as a parameterizable
1293type.
620db045 1294
e7fcb7b2 1295=item B<create_class_type_constraint($class, $options)>
dabed765 1296
e7fcb7b2 1297Given a class name this function will create a new
1298L<Moose::Meta::TypeConstraint::Class> object for that class name.
004222dc 1299
e7fcb7b2 1300The C<$options> is a hash reference that will be passed to the
1301L<Moose::Meta::TypeConstraint::Class> constructor (as a hash).
620db045 1302
e7fcb7b2 1303=item B<create_role_type_constraint($role, $options)>
620db045 1304
e7fcb7b2 1305Given a role name this function will create a new
1306L<Moose::Meta::TypeConstraint::Role> object for that role name.
620db045 1307
e7fcb7b2 1308The C<$options> is a hash reference that will be passed to the
1309L<Moose::Meta::TypeConstraint::Role> constructor (as a hash).
620db045 1310
8a6c8c47 1311=item B<create_enum_type_constraint($name, $values)>
1312
1313Given a enum name this function will create a new
1314L<Moose::Meta::TypeConstraint::Enum> object for that enum name.
1315
0a6bff54 1316=item B<create_duck_type_constraint($name, $methods)>
1317
1318Given a duck type name this function will create a new
1319L<Moose::Meta::TypeConstraint::DuckType> object for that enum name.
1320
e7fcb7b2 1321=item B<find_or_parse_type_constraint($type_name)>
620db045 1322
ec4b72d2 1323Given a type name, this first attempts to find a matching constraint
e7fcb7b2 1324in the global registry.
620db045 1325
e7fcb7b2 1326If the type name is a union or parameterized type, it will create a
1327new object of the appropriate, but if given a "regular" type that does
1328not yet exist, it simply returns false.
620db045 1329
e7fcb7b2 1330When given a union or parameterized type, the member or base type must
1331already exist.
620db045 1332
e7fcb7b2 1333If it creates a new union or parameterized type, it will add it to the
1334global registry.
004222dc 1335
e7fcb7b2 1336=item B<find_or_create_isa_type_constraint($type_name)>
004222dc 1337
e7fcb7b2 1338=item B<find_or_create_does_type_constraint($type_name)>
004222dc 1339
e7fcb7b2 1340These functions will first call C<find_or_parse_type_constraint>. If
72042ad7 1341that function does not return a type, a new type object will
e7fcb7b2 1342be created.
004222dc 1343
e7fcb7b2 1344The C<isa> variant will use C<create_class_type_constraint> and the
1345C<does> variant will use C<create_role_type_constraint>.
004222dc 1346
1347=item B<get_type_constraint_registry>
1348
e7fcb7b2 1349Returns the L<Moose::Meta::TypeConstraint::Registry> object which
004222dc 1350keeps track of all type constraints.
1351
1352=item B<list_all_type_constraints>
1353
e7fcb7b2 1354This will return a list of type constraint names in the global
1355registry. You can then fetch the actual type object using
1356C<find_type_constraint($type_name)>.
004222dc 1357
1358=item B<list_all_builtin_type_constraints>
1359
e7fcb7b2 1360This will return a list of builtin type constraints, meaning those
1361which are defined in this module. See the L<Default Type Constraints>
1362section for a complete list.
004222dc 1363
1364=item B<export_type_constraints_as_functions>
1365
e7fcb7b2 1366This will export all the current type constraints as functions into
1367the caller's namespace (C<Int()>, C<Str()>, etc). Right now, this is
1368mostly used for testing, but it might prove useful to others.
004222dc 1369
1370=item B<get_all_parameterizable_types>
1371
e7fcb7b2 1372This returns all the parameterizable types that have been registered,
1373as a list of type objects.
004222dc 1374
e7fcb7b2 1375=item B<add_parameterizable_type($type)>
004222dc 1376
1377Adds C<$type> to the list of parameterizable types
1378
1379=back
1380
a15dff8d 1381=head1 BUGS
1382
d4048ef3 1383See L<Moose/BUGS> for details on reporting bugs.
a15dff8d 1384
81dc201f 1385=cut